/** * Send a GET request to retrieve a byte range from the given URL. * * \param[out] buffer The buffer where the response will be written. * \param[in] bufferSize The size of the output buffer. * \param[in] host The remote host where the resource is located. * \param[in] path The path of the desired resource on the host. * \param[in] firstByte Index of the first byte of the requested range. * \param[in] lastByte Index of the last byte of the requested range. * * \return true is returned if the right amount of data is successfully * received, false in case of failure. * * \note host can be either the domain name or the IP address of the host. */ bool HttpClient::getRange(char* buffer, size_t bufferSize, const char* host, const char* path, uint32_t firstByte, uint32_t lastByte) { // generate the HTTP request if (!createGetRequest(buffer, bufferSize, host, path, (F_GET | F_KEEP_ALIVE), firstByte, lastByte)) { return false; } // try to send the request and wait for a response from the host wifly_->clear(); if (!wifly_->print(buffer)) return false; wifly_->flush(); // clear the buffer since it still holds the HTTP request memset(buffer, 0x00, bufferSize); if (!wifly_->awaitResponse()) return false; // look for the right HTTP status code in the response header if (!wifly_->findUntil_P(HTTP_PARTIAL, HTTP_END_OF_HEADER)) return false; // skip the rest of the header if (!wifly_->find_P(HTTP_END_OF_HEADER)) return false; // write incoming data int nBytes = wifly_->readBytes(buffer, bufferSize); return (nBytes == (lastByte - firstByte + 1)); }
QNetworkReply * TwitterQueryUtil::get(QNetworkAccessManager &network, const QString &path, const std::map<QByteArray, QByteArray> ¶meters, const Account &account) { QNetworkRequest request {createGetRequest(path, parameters, account)}; return network.get(request); }
/** * Send a HEAD request to retrieve the size of the resource located at the * given URL. * \param[out] buffer The buffer where the response will be written. * \param[in] bufferSize The size of the output buffer. * \param[in] host The remote host where the resource is located. * \param[in] path The path of the desired resource on the host. */ uint32_t HttpClient::getContentLength(char* buffer, size_t bufferSize, const char* host, const char* path) { if (!createGetRequest(buffer, bufferSize, host, path, (F_HEAD | F_KEEP_ALIVE))) return 0; wifly_->clear(); if (!wifly_->print(buffer)) return 0; wifly_->flush(); memset(buffer, 0x00, bufferSize); if (!wifly_->awaitResponse()) return 0; if (!wifly_->findUntil_P(HTTP_CONTENT_LENGTH, HTTP_END_OF_HEADER)) return 0; uint8_t nBytes = wifly_->readBytesUntil_P(HTTP_CRLF, buffer, 32); return atol(buffer); }
/* * Determine the size of the resource located at the given URL. * * \param[out] buffer The buffer where the response will be written. * \param[in] bufferSize The size of the output buffer. * \param[in] host The remote host where the resource is located. * \param[in] path The path of the desired resource on the host. * * \return The size of the file (in bytes) is returned. If an error occurs, the * value 0 is returned. * * \note This method is a workaround for determining the size of a file on the * SoundCloud servers. * * SoundCloud songs are hosted either on ec-media.soundcloud.com or on * ak-media.soundcloud.com, and the latter does not support HEAD requests. * * In order to retrieve a Content-Length header from ak-media.soundcloud.com, * we send a partial GET request with a very small range (only a few bytes) so * that we get the response headers. */ uint32_t SoundCloud::getLengthFromHeader(char* buffer, size_t bufferSize, url_t& url) { // create a partial GET request asking for only two bytes uint8_t flags = (F_GET | F_KEEP_ALIVE); if (!createGetRequest(buffer, bufferSize, url.host, url.path, flags, 0, 1)) return false; wifly_->clear(); if (!wifly_->print(buffer)) return 0; memset(buffer, 0x00, bufferSize); if (!wifly_->awaitResponse()) return 0; // parse the size of the file from the Content-Range header if (!wifly_->findUntil_P(HTTP_CONTENT_RANGE, HTTP_END_OF_HEADER)) return 0; memset(buffer, 0x00, 33); uint8_t nBytes = wifly_->readBytesUntil_P(HTTP_CRLF, buffer, 32); return atol(buffer); }
/** * Connect to host and send a GET request to retrieve the given URL. * * \param[out] buffer The buffer where the response will be written. * \param[in] bufferSize The size of the output buffer. * \param[in] host The remote host where the resource is located. * \param[in] path The path of the desired resource on the host. * * \return The number of bytes actually received, -1 in case of failure. * * \note host can be either the domain name or the IP address of the host. */ int HttpClient::get(char* buffer, size_t bufferSize, const char* host, const char* path) { // generate the HTTP request if (!createGetRequest(buffer, bufferSize, host, path, (F_GET | F_KEEP_ALIVE))) { return -1; } // try to send the request and wait for a response from the host wifly_->clear(); if (!wifly_->print(buffer)) return -1; wifly_->flush(); // clear the buffer since it still holds the HTTP request memset(buffer, 0x00, bufferSize); if (!wifly_->awaitResponse()) return -1; // determine transfer mode bool chunked = wifly_->findUntil_P(HTTP_CHUNKED, HTTP_END_OF_HEADER); if (chunked) { // skip the rest of the header if (!wifly_->find_P(HTTP_END_OF_HEADER)) return -1; // process successive chunks uint16_t index = 0; while (index < bufferSize - 1) { char parseBuffer[SSCANF_BUFFER_SIZE]; // read the line containing the chunk size int nBytes = wifly_->readBytesUntil_P(HTTP_CRLF, parseBuffer, SSCANF_BUFFER_SIZE); // chunk size should be at least one digit followed by \r\n if (nBytes < 1 + strlen_P(HTTP_CRLF)) return -1; // erase the \r\n memset(parseBuffer + nBytes - 2, 0x00, 2); // parse chunk size uint16_t chunkSize = 0; sscanf(parseBuffer, "%x", &chunkSize); if (chunkSize < 0 || chunkSize > bufferSize) { return -1; } if (chunkSize == 0) break; // download chunk nBytes = wifly_->readBytes(buffer + index, chunkSize); if (nBytes != chunkSize) return -1; index += chunkSize; // skip end of line if (!wifly_->find_P(HTTP_CRLF)) return -1; } return index; } else { int nBytes = wifly_->readBytes(buffer, bufferSize); return nBytes; } }