📄 c_http.c
字号:
switch (ret) {
case SOCKET_ERROR:
case SOCKET_CLOSED:
return readByte;
case SOCKET_TIMEOUT:
break;
default:
#ifdef PROCESS_EXTRA
if (pHeaders->processExtraResponse != NULL) {
if (!(*(pHeaders->processExtraResponse))(
pHeaders->extraResp,
ret,
&(pHeaders->respProcessed),
response,
size
))
{
return readByte;
}
}
#endif
break;
}
}
return readByte;
}
/* 发送HTTP请求,内部函数,输入参数line的初始内容为请求行 */
static int sendHTTPRequest(int hSocket, char* line, const char* inHeaders, URLINFO* urlInfo, int timeout)
{
int err = SOCKET_ERROR;
if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
{
goto EXIT;
}
sprintf(line, "Host: %s", urlInfo->host);
if (urlInfo->port != DEFAULT_PORT)
{
sprintf(line + strlen(line), ":%d", urlInfo->port);
}
if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
{
goto EXIT;
}
if (SendLine(hSocket, CONTENT_TYPE, timeout) == SOCKET_ERROR)
{
goto EXIT;
}
if (SendLine(hSocket, USER_AGENT, timeout) == SOCKET_ERROR)
{
goto EXIT;
}
if (urlInfo->user != NULL)
{
char auth[512];
int len;
len = sprintf(line, "%s:%s", urlInfo->user, urlInfo->passwd==NULL?"":urlInfo->passwd);
len = Base64Encode(line, len, auth, 511, 0);
auth[len] = '\0';
sprintf(line, "%s %s", BASIC_AUTH, auth);
if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
{
goto EXIT;
}
}
/* 输出额外的头信息 */
if (inHeaders != NULL)
{
if (SendLine(hSocket, inHeaders, timeout) == SOCKET_ERROR)
{
goto EXIT;
}
}
err = 0;
EXIT:
return err;
}
/**
* 以HEAD方式做HTTP请求
* IN:
* url: HTTP的URL,可以带query_string('?'后面的部分),例:http://user:passwd@host:port/file?query
* inHeaders: 请求头信息,如设置cookie的头信息,可以传NULL,格式是:"Header1: value1\nHeader2: value2",最后一个不加'\n'
* outHeaders: 响应的头信息,见HTTP_RESPONSE_HEADER_T定义,必须不为NULL
* timeout: 访问超时秒数,传0使用缺省值
* OUT:
* 0: 发生错误,错误原因可看headers中的errMsg
* >0: 请求成功,这时headers中的errMsg为NULL,其余信息见headers中其它字段
*/
int HTTPRequestHead(const char* url, const char* inHeaders, HTTP_RESPONSE_HEADER_T* outHeaders, int timeout)
{
int errno = NO_ERROR;
URLINFO urlInfo = {0};
char line[1024];
int len = 0;
int hSocket = INVALID_SOCKET;
if (outHeaders == NULL || !validHTTPParams(url, outHeaders, "", 1, &urlInfo))
{
return 0;
}
timeout = getResponseTimeOut(timeout);
hSocket = NonbSocket(urlInfo.host, urlInfo.port, timeout);
if (hSocket == INVALID_SOCKET)
{
errno = CONNECTION_ERROR;
goto EXIT;
}
/* send HTTP Request */
sprintf(line, "HEAD %s HTTP/1.0", urlInfo.file);
if (sendHTTPRequest(hSocket, line, inHeaders, &urlInfo, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
if (SendLine(hSocket, BLANK_LINE, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
/* read response */
len = readResponse(hSocket, outHeaders, line, NULL, 0, &errno, timeout);
EXIT:
freeURLInfo(&urlInfo);
if (hSocket != INVALID_SOCKET)
{
CloseSocket(hSocket);
}
if (outHeaders != NULL)
{
outHeaders->errMsg = ERROR_MESSAGE[errno];
}
return len;
}
/**
* 以GET方式做HTTP请求
* IN:
* url: HTTP的URL,可以带query_string('?'后面的部分),例:http://user:passwd@host:port/file?query
* inHeaders: 请求头信息,如设置cookie的头信息,可以传NULL,格式是:"Header1: value1\nHeader2: value2",最后一个不加'\n'
* outHeaders: 响应的头信息,见HTTP_RESPONSE_HEADER_T定义,可以传NULL
* timeout: 访问超时秒数,传0使用缺省值
* response: 存放响应结果的内存区
* size: response的空间大小
* OUT:
* 0: 发生错误,错误原因可看headers中的errMsg
* >0: response中的有效字符数,这时headers中的errMsg为NULL
* 【注意】:response中不会添加字符串结束标志'\0',因为结果也可以是二进制内容
*/
int HTTPRequestGet(const char* url, const char* inHeaders, HTTP_RESPONSE_HEADER_T* outHeaders, int timeout, char* response, int size)
{
int errno = NO_ERROR;
URLINFO urlInfo = {0};
char line[1024];
int len = 0;
int hSocket = INVALID_SOCKET;
if (!validHTTPParams(url, outHeaders, response, size, &urlInfo))
{
return 0;
}
timeout = getResponseTimeOut(timeout);
hSocket = NonbSocket(urlInfo.host, urlInfo.port, timeout);
if (hSocket == INVALID_SOCKET)
{
errno = CONNECTION_ERROR;
goto EXIT;
}
/* send HTTP Request */
sprintf(line, "GET %s HTTP/1.0", urlInfo.file);
if (sendHTTPRequest(hSocket, line, inHeaders, &urlInfo, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
if (SendLine(hSocket, BLANK_LINE, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
/* read response */
len = readResponse(hSocket, outHeaders, line, response, size, &errno, timeout);
EXIT:
freeURLInfo(&urlInfo);
if (hSocket != INVALID_SOCKET)
{
CloseSocket(hSocket);
}
if (outHeaders != NULL)
{
outHeaders->errMsg = ERROR_MESSAGE[errno];
}
return len;
}
/**
* 以POST方式做HTTP请求
* IN:
* url: HTTP的URL,可以带query_string('?'后面的部分),例:http://user:passwd@host:port/file?query
* postBody: 需要通过POST方式传送的数据,如果为NULL,会传送url中的query_string部分
* bodyLen: postBody的长度,因为postBody可以是二进制内容,如果postBody为NULL时可传任意值
* inHeaders: 请求头信息,如设置cookie的头信息,可以传NULL,格式是:"Header1: value1\nHeader2: value2",最后一个不加'\n'
* outHeaders: 响应的头信息,见HTTP_RESPONSE_HEADER_T定义,可以传NULL
* timeout: 访问超时秒数,传0使用缺省值
* response: 存放响应结果的内存区
* size: response的空间大小
* OUT:
* 0: 发生错误,错误原因可看headers中的errMsg
* >0: response中的有效字符数,这时headers中的errMsg为NULL
* 【注意】:response中不会添加字符串结束标志'\0',因为结果也可以是二进制内容
*/
int HTTPRequestPost(const char* url, const char* postBody, int bodyLen, const char* inHeaders, HTTP_RESPONSE_HEADER_T* outHeaders, int timeout, char* response, int size)
{
int errno = NO_ERROR;
URLINFO urlInfo = {0};
char line[1024];
int len = 0;
const char* body;
int hSocket = INVALID_SOCKET;
if (!validHTTPParams(url, outHeaders, response, size, &urlInfo))
{
return 0;
}
/* 取body/bodyLen */
if (postBody != NULL)
{
body = postBody;
}
else
{
body = urlInfo.query;
if (body != NULL)
{
*((char*)(body-1)) = '\0'; /* URL中的'?'设为0 */
bodyLen = strlen(body);
}
else
{
bodyLen = 0;
}
}
timeout = getResponseTimeOut(timeout);
hSocket = NonbSocket(urlInfo.host, urlInfo.port, timeout);
if (hSocket == INVALID_SOCKET)
{
errno = CONNECTION_ERROR;
goto EXIT;
}
/* send HTTP Request */
sprintf(line, "POST %s HTTP/1.0", urlInfo.file);
if (sendHTTPRequest(hSocket, line, inHeaders, &urlInfo, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
sprintf(line, "Content-Length: %d", bodyLen);
if (SendLine(hSocket, line, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
if (SendLine(hSocket, BLANK_LINE, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
//send request body
if (bodyLen > 0)
{
if (Send(hSocket, (const char*)body, bodyLen, timeout) == SOCKET_ERROR)
{
errno = COMM_ERROR;
goto EXIT;
}
}
/* read response */
len = readResponse(hSocket, outHeaders, line, response, size, &errno, timeout);
EXIT:
freeURLInfo(&urlInfo);
if (hSocket != INVALID_SOCKET)
{
CloseSocket(hSocket);
}
if (outHeaders != NULL)
{
outHeaders->errMsg = ERROR_MESSAGE[errno];
}
return len;
}
/* 测试用 */
void dumpResponseHeaders(HTTP_RESPONSE_HEADER_T* headers, FILE* out)
{
if (headers == NULL || out == NULL)
{
return;
}
fprintf(out, "Error: %s\n"
"statusCode: %s\n"
"Content-Type: %s\n"
"Content-Length: %d\n"
"Date: %s\n"
"Server: %s\n"
"Last-Modified: %s\n"
"Location: %s\n",
(headers->errMsg?headers->errMsg:NO_HEADER),
(headers->statusCode[0]?headers->statusCode:NO_HEADER),
(headers->contentType[0]?headers->contentType:NO_HEADER),
headers->contentLength,
(headers->date[0]?headers->date:NO_HEADER),
(headers->server[0]?headers->server:NO_HEADER),
(headers->lastModified[0]?headers->lastModified:NO_HEADER),
(headers->location[0]?headers->location:NO_HEADER)
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -