#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #include namespace http { std::string get(std::string host, int port, std::string page) { HINTERNET hInternet = ::InternetOpenA("md639 MarsLander", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hInternet) throw std::runtime_error("Couldn't open the internet."); HINTERNET hConnect = ::InternetConnectA(hInternet, host.c_str(), (INTERNET_PORT)port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL); if (!hConnect) { ::InternetCloseHandle(hInternet); throw std::runtime_error("Unable to connect to the server."); } // Should be application/json, but accept text as a backup LPCSTR aszAccept[] = { "application/json", "text/*", NULL }; HINTERNET hRequest = ::HttpOpenRequestA(hConnect, NULL, page.c_str(), NULL, NULL, aszAccept, INTERNET_FLAG_NO_COOKIES, NULL); if (!hRequest) { ::InternetCloseHandle(hConnect); ::InternetCloseHandle(hInternet); throw std::runtime_error("Error opening request."); } BOOL r = ::HttpSendRequestA(hRequest, NULL, 0, NULL, 0); if (!r) { ::InternetCloseHandle(hRequest); ::InternetCloseHandle(hConnect); ::InternetCloseHandle(hInternet); throw std::runtime_error("Error sending request."); } DWORD cbContent; DWORD cbcbContent = sizeof(cbContent); r = HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH, &cbContent, &cbcbContent, NULL); if (!r) { int n = GetLastError(); if (n == ERROR_HTTP_HEADER_NOT_FOUND) { cbContent = 1024; } else { ::InternetCloseHandle(hRequest); ::InternetCloseHandle(hConnect); ::InternetCloseHandle(hInternet); throw std::runtime_error("Couldn't query content length."); } } std::string ret = ""; char* lpBuffer = new char[cbContent+1]; DWORD cbRead = 0; do { ::InternetReadFile(hRequest, lpBuffer, cbContent, &cbRead); ret.append(lpBuffer, cbRead); } while (cbRead != 0); delete[] lpBuffer; ::InternetCloseHandle(hRequest); ::InternetCloseHandle(hConnect); ::InternetCloseHandle(hInternet); return ret; } } #else #include #include #include #include #include #include #include namespace http { int create_tcp_socket(); std::string get_ip( std::string host ); std::string build_get_query( std::string host, std::string page ); std::string get( std::string host, int port, std::string page ) { sockaddr_in* remote; int sock; int tmpres; std::string ip; std::string get; std::string buf; buf.resize( BUFSIZ + 1 ); sock = create_tcp_socket(); ip = get_ip( host ); remote = new sockaddr_in; remote->sin_family = AF_INET; tmpres = inet_pton( AF_INET, ip.c_str(), &( remote->sin_addr.s_addr ) ); if ( tmpres < 0 ) { throw std::runtime_error( "Can't set remote->sin_addr.s_addr" ); } else if ( tmpres == 0 ) { throw std::invalid_argument( "IP Address not valid." ); } remote->sin_port = htons( port ); if ( connect( sock, ( sockaddr* )remote, sizeof( sockaddr ) ) < 0 ) { throw std::runtime_error( "Could not connect to socket." ); } get = build_get_query( host, page ); //Send the query to the server unsigned int sent = 0; while ( sent < get.length() ) { tmpres = send( sock, get.c_str() + sent, get.length() - sent, 0 ); if ( tmpres == -1 ) { throw std::runtime_error( "Could not send request." ); } sent += tmpres; } //now it is time to receive the page unsigned int htmlstart = 0; bool seen = false; std::ostringstream oss; while ( ( tmpres = recv( sock, &buf[0], BUFSIZ, 0 ) ) > 0 ) { if ( !seen ) { htmlstart = buf.find( "\r\n\r\n" ); if ( htmlstart != std::string::npos ) { seen = true; oss << &buf.c_str()[htmlstart + 4]; } } else { oss << buf; } buf.clear(); } delete remote; close( sock ); return oss.str(); } int create_tcp_socket() { int sock; sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( sock < 0 ) { throw std::runtime_error( "Can't create TCP socket" ); } return sock; } std::string get_ip( std::string host ) { hostent* hent; const int iplen = 15; std::string ip; ip.resize( iplen + 1 ); hent = gethostbyname( host.c_str() ); if ( !hent ) { throw std::runtime_error( "Unable to get IP." ); } if ( !inet_ntop( AF_INET, hent->h_addr_list[0], &ip[0], iplen ) ) { throw std::runtime_error( "Unable to resolve host." ); } return ip; } std::string build_get_query( std::string host, std::string page ) { std::ostringstream oss; oss << "GET " << ( ( page[0] == '/' ) ? "" : "/" ) << page << " HTTP/1.0\r\n" << "Host: " << host << "\r\n" << "User-Agent: md639 MarsLander\r\n\r\n"; return oss.str(); } } #endif