📄 a_httpreq.cpp
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2006 Send HTTP request to server, specified by the command line and rURI Build: make a_httpreq*/#include "../src/wystr.h"#include "../src/wysockfile.h"#include "../src/wysockaddrinet4.h"#include "../src/wysockaddrinet6.h"#include "../src/wy_uty.h"#include "../src/wy_atdestroy.h"#include <netdb.h>#include <new>// Class inheriting WY_RepInfo for macro EAI_... from ::getaddrinfo.(very basic)// Error text is borrowed from <netdb.h> (LGPL checked)//class EAI_ErrInfo : public Wy_RepInfo { public: EAI_ErrInfo(int ec, const char* cstr) throw() : Wy_RepInfo(ec,cstr) {}; size_t get_reply(char* buf, size_t blen) const WY__NOTHROW__ { return Wy_RepInfo::get_reply(buf,blen); }; void set_reply(const char* str, size_t slen) WY__NOTHROW__ {}; // no effect};static EAI_ErrInfo ei_EAI_BADFLAGS(EAI_BADFLAGS,"Invalid value for `ai_flags' field");static EAI_ErrInfo ei_EAI_NONAME(EAI_NONAME,"NAME or SERVICE is unknown");static EAI_ErrInfo ei_EAI_AGAIN(EAI_AGAIN,"Temporary failure in name resolution");static EAI_ErrInfo ei_EAI_FAIL(EAI_FAIL,"Non-recoverable failure in name res");static EAI_ErrInfo ei_EAI_NODATA(EAI_NODATA,"No address associated with NAME");static EAI_ErrInfo ei_EAI_FAMILY(EAI_FAMILY,"`ai_family' not supported");static EAI_ErrInfo ei_EAI_SOCKTYPE(EAI_SOCKTYPE,"`ai_socktype' not supported");static EAI_ErrInfo ei_EAI_SERVICE(EAI_SERVICE,"SERVICE not supported for `ai_socktype'");static EAI_ErrInfo ei_EAI_ADDRFAMILY(EAI_ADDRFAMILY,"Address family for NAME not supported");static EAI_ErrInfo ei_EAI_MEMORY(EAI_MEMORY,"Memory allocation failure");static EAI_ErrInfo ei_EAI_SYSTEM(EAI_SYSTEM,"System error returned in `errno'");static EAI_ErrInfo ei_EAI_OVERFLOW(EAI_OVERFLOW,"Argument buffer overflow");const WyReply Wym_EAI_BADFLAGS(ei_EAI_BADFLAGS);const WyReply Wym_EAI_NONAME(ei_EAI_NONAME);const WyReply Wym_EAI_AGAIN(ei_EAI_AGAIN);const WyReply Wym_EAI_FAIL(ei_EAI_FAIL);const WyReply Wym_EAI_NODATA(ei_EAI_NODATA);const WyReply Wym_EAI_FAMILY(ei_EAI_FAMILY);const WyReply Wym_EAI_SOCKTYPE(ei_EAI_SOCKTYPE);const WyReply Wym_EAI_SERVICE(ei_EAI_SERVICE);const WyReply Wym_EAI_ADDRFAMILY(ei_EAI_ADDRFAMILY);const WyReply Wym_EAI_MEMORY(ei_EAI_MEMORY);const WyReply Wym_EAI_SYSTEM(ei_EAI_SYSTEM);const WyReply Wym_EAI_OVERFLOW(ei_EAI_OVERFLOW);// The '::getaddrinfo' function this file uses, mainly for return status// conversion//static WyRet wy_getaddrinfo(const char* node, const char* service, const struct addrinfo* hints, struct addrinfo** res){ const int v=::getaddrinfo(node,service,hints,res); if(v==0) { return( Ok ); } WyRet r; switch(v) { case EAI_FAMILY: r= Wym_EAI_FAMILY ; break; case EAI_SOCKTYPE: r= Wym_EAI_SOCKTYPE ; break; case EAI_BADFLAGS: r= Wym_EAI_BADFLAGS ; break; case EAI_NONAME: r= Wym_EAI_NONAME ; break; case EAI_SERVICE: r= Wym_EAI_SERVICE ; break; case EAI_ADDRFAMILY: r= Wym_EAI_ADDRFAMILY ; break; case EAI_NODATA: r= Wym_EAI_NODATA ; break; case EAI_MEMORY: r= Wym_EAI_MEMORY ; break; case EAI_FAIL: r= Wym_EAI_FAIL ; break; case EAI_AGAIN: r= Wym_EAI_AGAIN ; break; case EAI_SYSTEM: r= Wym_EAI_SYSTEM ; break; case EAI_OVERFLOW: r= Wym_EAI_OVERFLOW ; break; default: WY_THROW( WyRet() ); }; WY_RETURN(r);};// [Syn] Write addr notation to Wy::cout//WyRet print_sockaddr(const Wy_SockAddr& addr)try { WyStr str; WyRet r( addr.notation(str) ); if(r!=Ok) { WY_RETURN(r); } size_t n_wr; if((r=Wy::full_write(Wy::cout,str,n_wr))!=Ok) { WY_RETURN(r); } if(n_wr!=str.size()) { WY_RETURN( Wym_EIO ); } return(Ok);}catch(const WyStr::Reply& e) { WY_RETURN(e);}catch(const WyRet& e) { WY_THROW( WyRet(e) );};// [Syn] Get socket address object converted from addr.ai_addr//// [Ret] Pointer to socket address object allocated from addr.ai_addr// , or NULL if failed// // Note: App. is responsible to delete the return object//static Wy_SockAddr* get_sockaddr(const struct ::addrinfo& addr){ switch(addr.ai_addr->sa_family) { case AF_INET: return new(std::nothrow) WySockAddrINet4( *(struct sockaddr_in*)addr.ai_addr ); case AF_INET6: return new(std::nothrow) WySockAddrINet6( *(struct sockaddr_in6*)addr.ai_addr ); default: return NULL; };};static WyRet http_client(const WyStr& domain_name, const WyStr& ruri)try { const char* Service="http"; struct addrinfo hints,*addr; WyRet r; ::memset(&hints,0,sizeof(hints)); hints.ai_socktype= SOCK_STREAM; // call getaddrinfo, result is allocated and pointed by addr for(;;) { const WyRet v( wy_getaddrinfo(domain_name.c_str(),Service,&hints,&addr) ); if(v==Ok) { break; } if(v==Wym_EAI_AGAIN) { continue; } WY_RETURN(v); } Wy_AtDestroy<void,struct addrinfo*> rrid(::freeaddrinfo,addr); // loop each addrinfo and request domain_name+ruri for(struct addrinfo *pa=addr; pa!=NULL; pa=pa->ai_next) { Wy_SockAddr *sa_ptr= get_sockaddr(*pa); if(sa_ptr==NULL) { WY_RETURN(Wym_ESRCH); // no address found (or ENOMEM) } Wy_AtDestroy<void,Wy_SockAddr*> rrid(Wy::_delete_one,sa_ptr); if((r=print_sockaddr(*sa_ptr))!=Ok) { WY_RETURN(r); } // connect to *sa_ptr pointed Http server, request for / const WyCSeg ReqHdr("GET "); const WyCSeg ReqTrail(" HTTP/1.0\r\n\r\n"); WyStr hmsg(ReqHdr+"http://"+domain_name+ruri+ReqTrail); Wy::cout << "Send Request>" << hmsg << '\n'; WySockFile sock; if((r=sock.reset(sa_ptr->family(),SOCK_STREAM,0))!=Ok) { Wy::cerr << Wy::wrd(r) << '\n'; continue; } if((r=sock.connect(*sa_ptr))!=Ok) { Wy::cerr << Wy::wrd(r) << '\n'; continue; } // send header/request message sock << hmsg; // get response untill eof { WyStr rbuf; for(;;) { sock >> rbuf; if(rbuf.size()==0) { break; // EOF } Wy::cout << rbuf; } } break; }; return(Ok);}catch(const WySockFile::Reply& e) { WY_RETURN(e);}catch(const WyStr::Reply& e) { WY_RETURN(e);}catch(const WySysFile::Reply& e) { WY_RETURN(e);}catch(const WyRet& e) { WY_TERMINATE("unexpected Reply");};static const char* syntax= "Syntax>./a_httpreq dn ru\n" " dn= Domain name. E.g. www.linux.org\n" " ru= Absolute URI. E.g. /\n";int main(int argc, char* argv[])try { if(argc!=3) { Wy::cerr << syntax; return(-1); } const WyRet r( http_client( WyCSeg(argv[1]), WyCSeg(argv[2])) ); if(r!=Ok) { Wy::cerr << Wy::wrd(r) << '\n'; } Wy::cout << "Ok\n"; return(0);}catch(...) { Wy::cerr << "Unidentified throw type\n"; return(-1);};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -