Пример #1
0
apr_status_t WriteBodyCallback(request_rec *r, char *buf, unsigned int length)
{
	REQUEST_STORED_CONTEXT *rsc = RetrieveIISContext(r);

	if(rsc == NULL || rsc->m_pRequestRec == NULL)
		return APR_SUCCESS;

	IHttpContext *pHttpContext = rsc->m_pHttpContext;
	IHttpRequest *pHttpRequest = pHttpContext->GetRequest();

    CHAR szLength[21]; //Max length for a 64 bit int is 20

    ZeroMemory(szLength, sizeof(szLength));

    HRESULT hr = StringCchPrintfA(
            szLength, 
            sizeof(szLength) / sizeof(CHAR) - 1, "%d", 
            length);

    if(FAILED(hr))
    {
		// not possible
    }

    hr = pHttpRequest->SetHeader(
            HttpHeaderContentLength, 
            szLength, 
            (USHORT)strlen(szLength),
            TRUE);

    if(FAILED(hr))
    {
		// possible, but there's nothing we can do
    }

	// since we clean the APR pool at the end of OnSendRequest, we must get IIS-managed memory chunk
	//
	void *reqbuf = pHttpContext->AllocateRequestMemory(length);

	memcpy(reqbuf, buf, length);

	pHttpRequest->InsertEntityBody(reqbuf, length);

	return APR_SUCCESS;
}
Пример #2
0
apr_status_t ReadBodyCallback(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)
{
	REQUEST_STORED_CONTEXT *rsc = RetrieveIISContext(r);

	*readcnt = 0;

	if(rsc == NULL)
	{
		*is_eos = 1;
		return APR_SUCCESS;
	}

	IHttpContext *pHttpContext = rsc->m_pHttpContext;
	IHttpRequest *pRequest = pHttpContext->GetRequest();

	if(pRequest->GetRemainingEntityBytes() == 0)
	{
		*is_eos = 1;
		return APR_SUCCESS;
	}

	HRESULT hr = pRequest->ReadEntityBody(buf, length, false, (DWORD *)readcnt, NULL);

	if (FAILED(hr))
    {
        // End of data is okay.
        if (ERROR_HANDLE_EOF != (hr  & 0x0000FFFF))
        {
            // Set the error status.
            rsc->m_pProvider->SetErrorStatus( hr );
        }

		*is_eos = 1;
    }

	return APR_SUCCESS;
}
Пример #3
0
HRESULT CHttpProtocol::SerializeRequestHeaders(CNodeHttpStoredContext* ctx, void** result, DWORD* resultSize, DWORD* resultLength)
{
	HRESULT hr;
	PCSTR originalUrl = NULL;
	USHORT originalUrlLength;
	DWORD remoteHostSize = INET6_ADDRSTRLEN + 1;
	char remoteHost[INET6_ADDRSTRLEN + 1];
	BOOL addXFF;
	char** serverVars;
	int serverVarCount;

	CheckNull(ctx);
	CheckNull(result);
	CheckNull(resultSize);
	CheckNull(resultLength);

	IHttpContext* context = ctx->GetHttpContext();

	DWORD bufferLength = CModuleConfiguration::GetInitialRequestBufferSize(context);
	DWORD offset = 0;
	IHttpRequest* request = context->GetRequest();
	HTTP_REQUEST* raw = request->GetRawHttpRequest();
	USHORT major, minor;
	const int tmpSize = 256;
	char tmp[tmpSize];
	PCSTR method = request->GetHttpMethod();
	
	ErrorIf(NULL == (*result = context->AllocateRequestMemory(bufferLength)), ERROR_NOT_ENOUGH_MEMORY);	

	// Determine whether response entity body is to be expected

	if (method && 0 == strcmpi("HEAD", method))
	{
		// HEAD requests do not have response entity body
		// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

		ctx->SetExpectResponseBody(FALSE);
	}
	
	// Request-Line

	CheckError(CHttpProtocol::Append(context, method, 0, result, &bufferLength, &offset));
	CheckError(CHttpProtocol::Append(context, " ", 1, result, &bufferLength, &offset));
	CheckError(CHttpProtocol::Append(context, ctx->GetTargetUrl(), ctx->GetTargetUrlLength(), result, &bufferLength, &offset));
	request->GetHttpVersion(&major, &minor);
	if (1 == major && 1 == minor)
	{
		CheckError(CHttpProtocol::Append(context, " HTTP/1.1\r\n", 11, result, &bufferLength, &offset));
	}
	else if (1 == major && 0 == minor)
	{
		CheckError(CHttpProtocol::Append(context, " HTTP/1.0\r\n", 11, result, &bufferLength, &offset));
	}
	else
	{
		sprintf(tmp, " HTTP/%d.%d\r\n", major, minor);
		CheckError(CHttpProtocol::Append(context, tmp, 0, result, &bufferLength, &offset));
	}

	// Known headers

	for (int i = 0; i < HttpHeaderRequestMaximum; i++)
	{
		if (raw->Headers.KnownHeaders[i].RawValueLength > 0)
		{
			CheckError(CHttpProtocol::Append(context, CHttpProtocol::httpRequestHeaders[i], 0, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, ": ", 2, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, raw->Headers.KnownHeaders[i].pRawValue, raw->Headers.KnownHeaders[i].RawValueLength, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));
		}
	}

	// Unknown headers

	if (TRUE == (addXFF = CModuleConfiguration::GetEnableXFF(context)))
	{
		PSOCKADDR addr = request->GetRemoteAddress();
		DWORD addrSize = addr->sa_family == AF_INET ? sizeof SOCKADDR_IN : sizeof SOCKADDR_IN6;
		ErrorIf(0 != WSAAddressToString(addr, addrSize, NULL, remoteHost, &remoteHostSize), GetLastError());
	}

	for (int i = 0; i < raw->Headers.UnknownHeaderCount; i++)
	{
		CheckError(CHttpProtocol::Append(context, raw->Headers.pUnknownHeaders[i].pName, raw->Headers.pUnknownHeaders[i].NameLength, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, ": ", 2, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, raw->Headers.pUnknownHeaders[i].pRawValue, raw->Headers.pUnknownHeaders[i].RawValueLength, result, &bufferLength, &offset));

		if (addXFF && 15 == raw->Headers.pUnknownHeaders[i].NameLength && 0 == strcmpi("X-Forwarded-For", raw->Headers.pUnknownHeaders[i].pName))
		{
			// augment existing X-Forwarded-For header

			CheckError(CHttpProtocol::Append(context, ", ", 2, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, remoteHost, remoteHostSize - 1, result, &bufferLength, &offset));

			addXFF = FALSE;
		}

		CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));		
	}

	if (addXFF)
	{
		// add a new X-Forwarded-For header

		CheckError(CHttpProtocol::Append(context, "X-Forwarded-For: ", 17, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, remoteHost, remoteHostSize - 1, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));		
	}

	// promote server variables

	CheckError(CModuleConfiguration::GetPromoteServerVars(context, &serverVars, &serverVarCount));
	while (serverVarCount)
	{
		serverVarCount--;
		PCSTR varValue;
		DWORD varValueLength;
		if (S_OK == context->GetServerVariable(serverVars[serverVarCount], &varValue, &varValueLength))
		{
			CheckError(CHttpProtocol::Append(context, "X-iisnode-", 10, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, serverVars[serverVarCount], 0, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, ": ", 2, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, varValue, varValueLength, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));		
		}
	}

	// CRLF

	CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));

	*resultSize = bufferLength;
	*resultLength = offset;

	return S_OK;
Error:
	
	if (NULL != result)
	{
		*result = NULL;
	}
	if (NULL != resultLength)
	{
		*resultLength = 0;
	}
	if (NULL != resultSize)
	{
		*resultSize = 0;
	}

	return hr;
}
Пример #4
0
HRESULT CHttpProtocol::SerializeRequestHeaders(CNodeHttpStoredContext* ctx, void** result, DWORD* resultSize, DWORD* resultLength)
{
	HRESULT hr;
	PCSTR originalUrl = NULL;
	USHORT originalUrlLength;	

	CheckNull(ctx);
	CheckNull(result);
	CheckNull(resultSize);
	CheckNull(resultLength);

	IHttpContext* context = ctx->GetHttpContext();

	DWORD bufferLength = CModuleConfiguration::GetInitialRequestBufferSize(context);
	DWORD offset = 0;
	IHttpRequest* request = context->GetRequest();
	HTTP_REQUEST* raw = request->GetRawHttpRequest();
	USHORT major, minor;
	char tmp[256];
	PCSTR method = request->GetHttpMethod();
	
	ErrorIf(NULL == (*result = context->AllocateRequestMemory(bufferLength)), ERROR_NOT_ENOUGH_MEMORY);	

	// Determine whether response entity body is to be expected

	if (method && 0 == strcmpi("HEAD", method))
	{
		// HEAD requests do not have response entity body
		// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

		ctx->SetExpectResponseBody(FALSE);
	}
	
	// Request-Line

	CheckError(CHttpProtocol::Append(context, method, 0, result, &bufferLength, &offset));
	CheckError(CHttpProtocol::Append(context, " ", 1, result, &bufferLength, &offset));
	CheckError(CHttpProtocol::Append(context, ctx->GetTargetUrl(), ctx->GetTargetUrlLength(), result, &bufferLength, &offset));
	request->GetHttpVersion(&major, &minor);
	if (1 == major && 1 == minor)
	{
		CheckError(CHttpProtocol::Append(context, " HTTP/1.1\r\n", 11, result, &bufferLength, &offset));
	}
	else if (1 == major && 0 == minor)
	{
		CheckError(CHttpProtocol::Append(context, " HTTP/1.0\r\n", 11, result, &bufferLength, &offset));
	}
	else
	{
		sprintf(tmp, " HTTP/%d.%d\r\n", major, minor);
		CheckError(CHttpProtocol::Append(context, tmp, 0, result, &bufferLength, &offset));
	}

	// Known headers

	for (int i = 0; i < HttpHeaderRequestMaximum; i++)
	{
		if (raw->Headers.KnownHeaders[i].RawValueLength > 0)
		{
			CheckError(CHttpProtocol::Append(context, CHttpProtocol::httpRequestHeaders[i], 0, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, ": ", 2, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, raw->Headers.KnownHeaders[i].pRawValue, raw->Headers.KnownHeaders[i].RawValueLength, result, &bufferLength, &offset));
			CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));
		}
	}

	// Unknown headers

	for (int i = 0; i < raw->Headers.UnknownHeaderCount; i++)
	{
		CheckError(CHttpProtocol::Append(context, raw->Headers.pUnknownHeaders[i].pName, raw->Headers.pUnknownHeaders[i].NameLength, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, ": ", 2, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, raw->Headers.pUnknownHeaders[i].pRawValue, raw->Headers.pUnknownHeaders[i].RawValueLength, result, &bufferLength, &offset));
		CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));		
	}

	// CRLF

	CheckError(CHttpProtocol::Append(context, "\r\n", 2, result, &bufferLength, &offset));

	*resultSize = bufferLength;
	*resultLength = offset;

	return S_OK;
Error:
	
	if (NULL != result)
	{
		*result = NULL;
	}
	if (NULL != resultLength)
	{
		*resultLength = 0;
	}
	if (NULL != resultSize)
	{
		*resultSize = 0;
	}

	return hr;
}