📄 main.c
字号:
Routine Description:
The routine sends a HTTP response.
Arguments:
hReqQueue - Handle to the request queue.
pRequest - The parsed HTTP request.
StatusCode - Response Status Code.
pReason - Response reason phrase.
pEntityString - Response entity body.
Return Value:
Success/Failure.
--***************************************************************************/
DWORD
SendHttpResponse(
IN HANDLE hReqQueue,
IN PHTTP_REQUEST pRequest,
IN USHORT StatusCode,
IN PSTR pReason,
IN PSTR pEntityString
)
{
HTTP_RESPONSE response;
HTTP_DATA_CHUNK dataChunk;
DWORD result;
DWORD bytesSent;
//
// Initialize the HTTP response structure.
//
INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason);
//
// Add a known header.
//
ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
if(pEntityString)
{
//
// Add an entity chunk
//
dataChunk.DataChunkType = HttpDataChunkFromMemory;
dataChunk.FromMemory.pBuffer = pEntityString;
dataChunk.FromMemory.BufferLength = (ULONG) strlen(pEntityString);
response.EntityChunkCount = 1;
response.pEntityChunks = &dataChunk;
}
//
// Since we are sending all the entity body in one call, we don't have
// to specify the Content-Length.
//
result = HttpSendHttpResponse(
hReqQueue, // ReqQueueHandle
pRequest->RequestId, // Request ID
0, // Flags
&response, // HTTP response
NULL, // pReserved1
&bytesSent, // bytes sent (OPTIONAL)
NULL, // pReserved2 (must be NULL)
0, // Reserved3 (must be 0)
NULL, // LPOVERLAPPED (OPTIONAL)
NULL // pReserved4 (must be NULL)
);
if(result != NO_ERROR)
{
wprintf(L"HttpSendHttpResponse failed with %lu \n", result);
}
return result;
}
/***************************************************************************++
Routine Description:
The routine sends a HTTP response after reading the entity body.
Arguments:
hReqQueue - Handle to the request queue.
pRequest - The parsed HTTP request.
Return Value:
Success/Failure.
--***************************************************************************/
DWORD
SendHttpPostResponse(
IN HANDLE hReqQueue,
IN PHTTP_REQUEST pRequest
)
{
HTTP_RESPONSE response;
DWORD result;
DWORD bytesSent;
PUCHAR pEntityBuffer;
ULONG EntityBufferLength;
ULONG BytesRead;
ULONG TempFileBytesWritten;
HANDLE hTempFile;
TCHAR szTempName[MAX_PATH + 1];
#define MAX_ULONG_STR ((ULONG) sizeof("4294967295"))
CHAR szContentLength[MAX_ULONG_STR];
HTTP_DATA_CHUNK dataChunk;
ULONG TotalBytesRead = 0;
BytesRead = 0;
hTempFile = INVALID_HANDLE_VALUE;
//
// Allocate some space for an entity buffer. We'll grow this on demand.
//
EntityBufferLength = 2048;
pEntityBuffer = ALLOC_MEM( EntityBufferLength );
if (pEntityBuffer == NULL)
{
result = ERROR_NOT_ENOUGH_MEMORY;
wprintf(L"Insufficient resources \n");
goto Done;
}
//
// Initialize the HTTP response structure.
//
INITIALIZE_HTTP_RESPONSE(&response, 200, "OK");
//
// For POST, we'll echo back the entity that we got from the client.
//
// NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
// flag with HttpReceiveHttpRequest(), the entity would have
// been a part of HTTP_REQUEST (using the pEntityChunks field).
// Since we have not passed that flag, we can be assured that
// there are no entity bodies in HTTP_REQUEST.
//
if(pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS)
{
// The entity body is send over multiple calls. Let's collect all
// of these in a file & send it back. We'll create a temp file
//
if(GetTempFileName(
L".",
L"New",
0,
szTempName
) == 0)
{
result = GetLastError();
wprintf(L"GetTempFileName failed with %lu \n", result);
goto Done;
}
hTempFile = CreateFile(
szTempName,
GENERIC_READ | GENERIC_WRITE,
0, // don't share.
NULL, // no security descriptor
CREATE_ALWAYS, // overrwrite existing
FILE_ATTRIBUTE_NORMAL, // normal file.
NULL
);
if(hTempFile == INVALID_HANDLE_VALUE)
{
result = GetLastError();
wprintf(L"Could not create temporary file. Error %lu \n", result);
goto Done;
}
do
{
//
// Read the entity chunk from the request.
//
BytesRead = 0;
result = HttpReceiveRequestEntityBody(
hReqQueue,
pRequest->RequestId,
0,
pEntityBuffer,
EntityBufferLength,
&BytesRead,
NULL
);
switch(result)
{
case NO_ERROR:
if(BytesRead != 0)
{
TotalBytesRead += BytesRead;
WriteFile(
hTempFile,
pEntityBuffer,
BytesRead,
&TempFileBytesWritten,
NULL
);
}
break;
case ERROR_HANDLE_EOF:
//
// We have read the last request entity body. We can send
// back a response.
//
// To illustrate entity sends via
// HttpSendResponseEntityBody, we will send the response
// over multiple calls. This is achieved by passing the
// HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag.
if(BytesRead != 0)
{
TotalBytesRead += BytesRead;
WriteFile(
hTempFile,
pEntityBuffer,
BytesRead,
&TempFileBytesWritten,
NULL
);
}
//
// Since we are sending the response over multiple API
// calls, we have to add a content-length.
//
// Alternatively, we could have sent using chunked transfer
// encoding, by passing "Transfer-Encoding: Chunked".
//
// NOTE: Since we are accumulating the TotalBytesRead in
// a ULONG, this will not work for entity bodies that
// are larger than 4 GB. For supporting large entity
// bodies, we would have to use a ULONGLONG.
//
sprintf(szContentLength, "%lu", TotalBytesRead);
ADD_KNOWN_HEADER(
response,
HttpHeaderContentLength,
szContentLength
);
result =
HttpSendHttpResponse(
hReqQueue, // ReqQueueHandle
pRequest->RequestId, // Request ID
HTTP_SEND_RESPONSE_FLAG_MORE_DATA,
&response, // HTTP response
NULL, // pReserved1
&bytesSent, // bytes sent (optional)
NULL, // pReserved2
0, // Reserved3
NULL, // LPOVERLAPPED
NULL // pReserved4
);
if(result != NO_ERROR)
{
wprintf(L"HttpSendHttpResponse failed with %lu \n",
result);
goto Done;
}
//
// Send entity body from a file handle.
//
dataChunk.DataChunkType =
HttpDataChunkFromFileHandle;
dataChunk.FromFileHandle.
ByteRange.StartingOffset.QuadPart = 0;
dataChunk.FromFileHandle.
ByteRange.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF;
dataChunk.FromFileHandle.FileHandle = hTempFile;
result = HttpSendResponseEntityBody(
hReqQueue,
pRequest->RequestId,
0, // This is the last send.
1, // Entity Chunk Count.
&dataChunk,
NULL,
NULL,
0,
NULL,
NULL
);
if(result != NO_ERROR)
{
wprintf(
L"HttpSendResponseEntityBody failed with %lu \n",
result
);
}
goto Done;
break;
default:
wprintf(L"HttpReceiveRequestEntityBody failed with %lu \n",
result);
goto Done;
}
} while(TRUE);
}
else
{
// This request does not have any entity body.
//
result = HttpSendHttpResponse(
hReqQueue, // ReqQueueHandle
pRequest->RequestId, // Request ID
0,
&response, // HTTP response
NULL, // pReserved1
&bytesSent, // bytes sent (optional)
NULL, // pReserved2
0, // Reserved3
NULL, // LPOVERLAPPED
NULL // pReserved4
);
if(result != NO_ERROR)
{
wprintf(L"HttpSendHttpResponse failed with %lu \n", result);
}
}
Done:
if(pEntityBuffer)
{
FREE_MEM(pEntityBuffer);
}
if(INVALID_HANDLE_VALUE != hTempFile)
{
CloseHandle(hTempFile);
DeleteFile(szTempName);
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -