예제 #1
0
/*----------------------------------------------------------------------
|   PLT_HttpServerSocketTask::SendResponseBody
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpServerSocketTask::SendResponseBody(NPT_HttpResponse* response,
                                           NPT_OutputStream& output_stream)
{
    NPT_HttpEntity* entity = response->GetEntity();
    if (!entity) return NPT_SUCCESS;

    NPT_InputStreamReference body_stream;
    entity->GetInputStream(body_stream);
    if (body_stream.IsNull()) return NPT_SUCCESS;

    // check for chunked transfer encoding
    NPT_OutputStream* dest = &output_stream;
    if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) {
        dest = new NPT_HttpChunkedOutputStream(output_stream);
    }

    // send body
    NPT_LOG_FINE_1("sending body stream, %lld bytes", entity->GetContentLength());
    NPT_LargeSize bytes_written = 0;
    NPT_Result result = NPT_StreamToStreamCopy(*body_stream, *dest, 0, entity->GetContentLength(), &bytes_written); /* passing 0 if content length is unknown will read until nothing is left */
    if (NPT_FAILED(result)) {
        NPT_LOG_FINE_3("body stream only partially sent, %lld bytes (%d:%s)",
                       bytes_written,
                       result,
                       NPT_ResultText(result));
    }

    // flush to write out any buffered data left in chunked output if used
    dest->Flush();

    // cleanup (this will send zero size chunk followed by CRLF)
    if (dest != &output_stream) delete dest;

    return result;
}
예제 #2
0
/*----------------------------------------------------------------------
|   PLT_HttpHelper::GetBody
+---------------------------------------------------------------------*/
NPT_Result 
PLT_HttpHelper::GetBody(NPT_HttpMessage& message, NPT_String& body) 
{
    NPT_Result res;
    NPT_InputStreamReference stream;

    // get stream
    NPT_HttpEntity* entity = message.GetEntity();
    if (!entity || NPT_FAILED(entity->GetInputStream(stream))) {
        return NPT_FAILURE;
    }

    // extract body
    NPT_StringOutputStream* output_stream = new NPT_StringOutputStream(&body);
    res = NPT_StreamToStreamCopy(*stream, *output_stream, 0, entity->GetContentLength());
    delete output_stream;
    return res;
}
/*----------------------------------------------------------------------
|       ShowResponse
+---------------------------------------------------------------------*/
static void
ShowResponse(NPT_HttpResponse* response)
{
    bool check_available = true;//true;
    
    // show entity
    NPT_HttpEntity* entity = response->GetEntity();
    if (entity == NULL) return;
    
    NPT_Console::OutputF("ENTITY: length=%lld, type=%s, encoding=%s\n",
                         entity->GetContentLength(),
                         entity->GetContentType().GetChars(),
                         entity->GetContentEncoding().GetChars());

    NPT_DataBuffer buffer(65536);
    NPT_Result result;
    NPT_InputStreamReference input;
    entity->GetInputStream(input);
    
    NPT_TimeStamp start;
    NPT_System::GetCurrentTimeStamp(start);
    float total_read = 0.0f;
    for (;;) {
        NPT_Size bytes_read = 0;
        NPT_LargeSize available = 0;
        NPT_Size to_read = 65536;
        if (check_available) {
            input->GetAvailable(available);
            if ((NPT_Size)available < to_read) to_read = (NPT_Size)available;
            if (to_read == 0) {
                to_read = 1;
                NPT_TimeStamp sleep_time(0.01f);
                NPT_System::Sleep(sleep_time);
            }
        }
        result = input->Read(buffer.UseData(), to_read, &bytes_read);
        if (NPT_FAILED(result)) break;
        total_read += bytes_read;
        NPT_TimeStamp now;
        NPT_System::GetCurrentTimeStamp(now);
        NPT_TimeStamp duration = now-start;
        NPT_Console::OutputF("%6d avail, read %6d bytes, %6.3f KB/s\n", (int)available, bytes_read, (float)((total_read/1024.0)/(double)duration));
    }
}
예제 #4
0
/*----------------------------------------------------------------------
|   PLT_Downloader::ProcessResponse
+---------------------------------------------------------------------*/
NPT_Result 
PLT_Downloader::ProcessResponse(NPT_Result                    res, 
                                const NPT_HttpRequest&        request, 
                                const NPT_HttpRequestContext& context, 
                                NPT_HttpResponse*             response)
{
    NPT_COMPILER_UNUSED(request);
    NPT_COMPILER_UNUSED(context);

    if (NPT_FAILED(res)) {
        NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars());
        m_State = PLT_DOWNLOADER_ERROR;
        return res;
    }

    m_State = PLT_DOWNLOADER_DOWNLOADING;

    NPT_HttpEntity* entity;
    NPT_InputStreamReference body;
    if (!response || 
        !(entity = response->GetEntity()) || 
        NPT_FAILED(entity->GetInputStream(body)) || 
        body.IsNull()) {
        m_State = PLT_DOWNLOADER_ERROR;
        NPT_LOG_WARNING_2("No body %d for %s", res, m_URL.ToString().GetChars());
        return NPT_FAILURE;
    }

    // Read body (no content length means until socket is closed)
    res = NPT_StreamToStreamCopy(*body.AsPointer(), 
        *m_Output.AsPointer(), 
        0, 
        entity->GetContentLength());

    if (NPT_FAILED(res)) {
        NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars());
        m_State = PLT_DOWNLOADER_ERROR;
        return res;
    }
    
    NPT_LOG_INFO_1("Finished downloading %s", m_URL.ToString().GetChars());
    m_State = PLT_DOWNLOADER_SUCCESS;
    return NPT_SUCCESS;
}
예제 #5
0
/*----------------------------------------------------------------------
|   PLT_Downloader::ProcessResponse
+---------------------------------------------------------------------*/
NPT_Result 
PLT_Downloader::ProcessResponse(NPT_Result                    res, 
                                NPT_HttpRequest*              request, 
                                const NPT_HttpRequestContext& context, 
                                NPT_HttpResponse* response)
{
    NPT_COMPILER_UNUSED(request);
    NPT_COMPILER_UNUSED(context);

    if (NPT_FAILED(res)) {
        m_State = PLT_DOWNLOADER_ERROR;
        return res;
    }

    m_State = PLT_DOWNLOADER_DOWNLOADING;

    NPT_HttpEntity* entity;
    NPT_InputStreamReference body;
    if (!response || !(entity = response->GetEntity()) || 
        NPT_FAILED(entity->GetInputStream(body)) || body.IsNull()) {
        m_State = PLT_DOWNLOADER_ERROR;
        return NPT_FAILURE;
    }

    // Read body (no content length means until socket is closed)
    res = NPT_StreamToStreamCopy(*body.AsPointer(), 
        *m_Output.AsPointer(), 
        0, 
        entity->GetContentLength());

    if (NPT_FAILED(res)) {
        m_State = PLT_DOWNLOADER_ERROR;
        return res;
    }

    m_State = PLT_DOWNLOADER_SUCCESS;
    return NPT_SUCCESS;
}
예제 #6
0
/*----------------------------------------------------------------------
|   PLT_HttpClient::SendRequest
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpClient::SendRequest(NPT_OutputStreamReference& output_stream, 
                            NPT_HttpRequest&           request, 
                            NPT_Timeout                timeout)
{
    NPT_COMPILER_UNUSED(timeout);

    // connect to the server
    NPT_LOG_FINE("Sending:");
    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);

    // add any headers that may be missing
    NPT_HttpHeaders& headers = request.GetHeaders();
    //headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close");
    if (!headers.GetHeader(NPT_HTTP_HEADER_USER_AGENT)) {
        headers.SetHeader(NPT_HTTP_HEADER_USER_AGENT, 
            "Platinum/" PLT_PLATINUM_VERSION_STRING);
    }

    // set host only if not already set
    if (!headers.GetHeader(NPT_HTTP_HEADER_HOST)) {
        NPT_String host = request.GetUrl().GetHost();
        if (request.GetUrl().GetPort() != NPT_HTTP_DEFAULT_PORT) {
            host += ":";
            host += NPT_String::FromInteger(request.GetUrl().GetPort());
        }
        headers.SetHeader(NPT_HTTP_HEADER_HOST, host);
    }

    // get the request entity to set additional headers
    NPT_InputStreamReference body_stream;
    NPT_HttpEntity* entity = request.GetEntity();
    if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
        // content length
        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, 
            NPT_String::FromInteger(entity->GetContentLength()));

        // content type
        NPT_String content_type = entity->GetContentType();
        if (!content_type.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
        }

        // content encoding
        NPT_String content_encoding = entity->GetContentEncoding();
        if (!content_encoding.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
        }
    } else {
        // force content length to 0 is there is no message body
        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
    }

    // create a memory stream to buffer the headers
    NPT_MemoryStream header_stream;

    // emit the request headers into the header buffer
    request.Emit(header_stream);

    // send the headers
    NPT_CHECK_SEVERE(output_stream->WriteFully(header_stream.GetData(), header_stream.GetDataSize()));

    // send request body
    if (!body_stream.IsNull() && entity->GetContentLength()) {
        NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(*body_stream.AsPointer(), *output_stream.AsPointer()));
    }

    // flush the output stream so that everything is sent to the server
    output_stream->Flush();

    return NPT_SUCCESS;
}
예제 #7
0
/*----------------------------------------------------------------------
|       ShowResponse
+---------------------------------------------------------------------*/
static void
ShowResponse(NPT_HttpResponse* response, ShowMode mode)
{
    // show response info
    NPT_Debug("RESPONSE: protocol=%s, code=%d, reason=%s\n",
              response->GetProtocol().GetChars(),
              response->GetStatusCode(),
              response->GetReasonPhrase().GetChars());

    // show headers
    NPT_HttpHeaders& headers = response->GetHeaders();
    NPT_List<NPT_HttpHeader*>::Iterator header = headers.GetHeaders().GetFirstItem();
    while (header) {
        NPT_Debug("%s: %s\n", 
          (const char*)(*header)->GetName(),
                  (const char*)(*header)->GetValue());
        ++header;
    }

    // show entity
    NPT_HttpEntity* entity = response->GetEntity();
    if (entity != NULL) {
        NPT_Debug("ENTITY: length=%lld, type=%s, encoding=%s\n",
                  entity->GetContentLength(),
                  entity->GetContentType().GetChars(),
                  entity->GetContentEncoding().GetChars());

        switch (mode) {
            case SHOW_MODE_LOAD: {
                NPT_DataBuffer body;
                NPT_Result result =entity->Load(body);
                if (NPT_FAILED(result)) {
                    NPT_Debug("ERROR: failed to load entity (%d)\n", result);
                } else {
                    NPT_Debug("BODY: loaded %d bytes\n", (int)body.GetDataSize());

                    // dump the body
                    NPT_OutputStreamReference output;
                    NPT_File standard_out(NPT_FILE_STANDARD_OUTPUT);
                    standard_out.Open(NPT_FILE_OPEN_MODE_WRITE);
                    standard_out.GetOutputStream(output);
                    NPT_Debug("%s", (char *)body.GetData());
                    // ÔÝʱ²»Ö§³Ö
                    // output->Write(body.GetData(), body.GetDataSize());
                }
                break;
            }
            
            case SHOW_MODE_STREAM_BLOCKING: {
                NPT_DataBuffer buffer(4096);
                NPT_Result result;
                NPT_InputStreamReference input;
                entity->GetInputStream(input);
                do {
                    NPT_Size bytes_read = 0;
                    result = input->Read(buffer.UseData(), 4096, &bytes_read);
                    NPT_Debug("read %d bytes\n", bytes_read);
                } while (NPT_SUCCEEDED(result));
                break;
            }
        }
    }
}
예제 #8
0
/*----------------------------------------------------------------------
|   PLT_HttpServerSocketTask::SendResponseHeaders
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpServerSocketTask::SendResponseHeaders(NPT_HttpResponse* response,
                                              NPT_OutputStream& output_stream,
                                              bool&             keep_alive)
{
    // add any headers that may be missing
    NPT_HttpHeaders& headers = response->GetHeaders();

    // get the request entity to set additional headers
    NPT_InputStreamReference body_stream;
    NPT_HttpEntity* entity = response->GetEntity();
    if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
        // set the content length if known
        if (entity->ContentLengthIsKnown()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH,
                              NPT_String::FromIntegerU(entity->GetContentLength()));
        }

        // content type
        NPT_String content_type = entity->GetContentType();
        if (!content_type.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
        }

        // content encoding
        NPT_String content_encoding = entity->GetContentEncoding();
        if (!content_encoding.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
        }
        
        // transfer encoding
        const NPT_String& transfer_encoding = entity->GetTransferEncoding();
        if (!transfer_encoding.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING, transfer_encoding);
        }
        
    } else if (!headers.GetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH)) {
        // force content length to 0 if there is no message body
		// (necessary for 1.1 or 1.0 with keep-alive connections)
        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
    }

    const NPT_String* content_length  = headers.GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH);
    const NPT_String* transfer_encoding  = headers.GetHeaderValue(NPT_HTTP_HEADER_TRANSFER_ENCODING);
    const NPT_String* connection_header  = headers.GetHeaderValue(NPT_HTTP_HEADER_CONNECTION);
    if (keep_alive) {
        if (connection_header && connection_header->Compare("close") == 0) {
            keep_alive = false;
        } else {
            // the request says client supports keep-alive
            // but override if response has content-length header or
            // transfer chunked encoding
            keep_alive = content_length ||
                (transfer_encoding && transfer_encoding->Compare(NPT_HTTP_TRANSFER_ENCODING_CHUNKED) == 0);
        }
    }

    // only write keep-alive header for 1.1 if it's close
    NPT_String protocol = response->GetProtocol();
    if (protocol.Compare(NPT_HTTP_PROTOCOL_1_0, true) == 0 || !keep_alive) {
        headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, keep_alive?"keep-alive":"close", true);
    }
    headers.SetHeader(NPT_HTTP_HEADER_SERVER, PLT_HTTP_DEFAULT_SERVER, false); // set but don't replace

    PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINE, "PLT_HttpServerSocketTask::Write", response);

    // create a memory stream to buffer the headers
    NPT_MemoryStream header_stream;
    response->Emit(header_stream);

    // send the headers
    NPT_CHECK_WARNING(output_stream.WriteFully(header_stream.GetData(), header_stream.GetDataSize()));

    return NPT_SUCCESS;
}