📄 httpreq.c
字号:
/* HTTPReq.c** HTTP REQUEST GENERATION**** (c) COPYRIGHT MIT 1995.** Please first read the full copyright statement in the file COPYRIGH.** @(#) $Id: HTTPReq.c,v 2.61 1999/02/22 22:10:12 frystyk Exp $**** This module implements the output stream for HTTP used for sending** requests with or without a entity body.**** History:** Jan 95 HFN Written from scratch*//* Library Includes */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "HTTPGen.h"#include "HTTPUtil.h"#include "HTTPReq.h" /* Implements */#define PUTC(c) (*me->target->isa->put_character)(me->target, c)#define PUTS(s) (*me->target->isa->put_string)(me->target, s)#define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)struct _HTStream { const HTStreamClass * isa; HTStream * target; HTRequest * request; SOCKET sockfd; int version; int state; char * url; BOOL transparent;};/* ------------------------------------------------------------------------- *//* HTTP Output Request Stream *//* ------------------------------------------------------------------------- *//* HTTP09Request** -------------** Makes a HTTP/0.9 request*/PRIVATE int HTTP09Request (HTStream * me, HTRequest * request){ HTParentAnchor * anchor = HTRequest_anchor(request); char * addr = HTAnchor_physical(anchor); if (!me->url) me->url = HTParse(addr, "", PARSE_PATH|PARSE_PUNCTUATION); if (me->state == 0) { int status = PUTS("GET "); if (status != HT_OK) return status; me->state++; } if (me->state == 1) { int status = PUTS(me->url); if (status != HT_OK) return status; me->state++; } PUTC(CR); PUTC(LF); HTTRACE(PROT_TRACE, "HTTP........ Generating HTTP/0.9 Request\n"); return HT_OK;}/* HTTPMakeRequest** ---------------** Makes a HTTP/1.0-1.1 request header.*/PRIVATE int HTTPMakeRequest (HTStream * me, HTRequest * request){ HTMethod method = HTRequest_method(request); HTRqHd request_mask = HTRequest_rqHd(request); HTParentAnchor * anchor = HTRequest_anchor(request); char * etag = HTAnchor_etag(anchor); char crlf[3]; char qstr[10]; *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0'; /* Generate the HTTP/1.x RequestLine */ if (me->state == 0) { if (method != METHOD_INVALID) { PUTS(HTMethod_name(method)); PUTC(' '); } else PUTS("GET "); me->state++; } /* ** Generate the Request URI. If we are using full request URI then it's ** easy. Otherwise we must filter out the path part of the URI. ** In case it's a OPTIONS request then if there is no pathinfo then use ** a * instead. If we use a method different from GET or HEAD then use ** the content-location if available. */ if (me->state == 1) { char * abs_location = NULL; char * addr = HTAnchor_physical(anchor);#if 0 /* ** We don't use the content-location any more as it is superseeded ** by etags and the combination of the two might do more harm than ** good (The etag is not guaranteed to be unique over multiple URIs) */ /* ** If we are using a method different from HEAD and GET then use ** the Content-Location if available, else the Request-URI. */ if (!HTMethod_isSafe(method)) { char * location = HTAnchor_location(anchor); if (location) { if (HTURL_isAbsolute(location)) addr = location; else { /* ** We have a content-location but it is relative and ** must expand it either to the content-base or to ** the Request-URI itself. */ char * base = HTAnchor_base(anchor); abs_location = HTParse(location, base, PARSE_ALL); addr = abs_location; } } }#endif /* ** If we are using a proxy or newer versions of HTTP then we can ** send the full URL. Otherwise we only send the path. */ if (HTRequest_fullURI(request)) StrAllocCopy(me->url, addr); else { me->url = HTParse(addr, "", PARSE_PATH | PARSE_PUNCTUATION); if (method == METHOD_OPTIONS) { /* ** We don't preserve the final slash or lack of same through ** out the code. This is mainly for optimization reasons ** but it gives a problem OPTIONS. We can either send a "*" ** or a "/" but not both. For now we send a "*". */ if (!strcmp(me->url, "/")) *me->url = '*'; } } HT_FREE(abs_location); me->state++; } /* ** Now send the URL that we have put together */ if (me->state == 2) { int status = HT_OK; if ((status = PUTS(me->url)) != HT_OK) return status; me->state++;#if 0 fprintf(stderr, "Requesting '%s'\n", me->url);#endif } PUTC(' '); /* ** Send out the version number. If we know it is a HTTP/1.0 server we ** are talking to then use HTTP/1.0, else use HTTP/1.1 as default version ** number */ if (me->version == HTTP_10) PUTS(HTTP_VERSION_10); else PUTS(HTTP_VERSION); PUTBLOCK(crlf, 2); /* Request Headers */ if (request_mask & HT_C_ACCEPT_TYPE) { HTFormat format = HTRequest_outputFormat(request); /* ** If caller has specified a specific output format then use this. ** Otherwise use all the registered converters to generate the ** accept header */ if (format == WWW_PRESENT) { int list; HTList *cur; BOOL first=YES; for (list=0; list<2; list++) { if ((!list && ((cur = HTFormat_conversion()) != NULL)) || (list && ((cur = HTRequest_conversion(request))!=NULL))) { HTPresentation * pres; while ((pres=(HTPresentation *) HTList_nextObject(cur))) { if (pres->rep_out==WWW_PRESENT && pres->quality<=1.0) { if (first) { PUTS("Accept: "); first=NO; } else PUTC(','); PUTS(HTAtom_name(pres->rep)); if (pres->quality < 1.0 && pres->quality >= 0.0) { sprintf(qstr, ";q=%1.1f", pres->quality); PUTS(qstr); } } } } } if (!first) PUTBLOCK(crlf, 2); } else { /* ** If we have an explicit output format then only send ** this one if not this is an internal libwww format ** of type www/<star> */ if (!HTMIMEMatch(WWW_INTERNAL, format)) { PUTS("Accept: "); PUTS(HTAtom_name(format)); PUTBLOCK(crlf, 2); } } } if (request_mask & HT_C_ACCEPT_CHAR) { int list; HTList *cur; BOOL first=YES; for (list=0; list<2; list++) { if ((!list && ((cur = HTFormat_charset()) != NULL)) || (list && ((cur = HTRequest_charset(request)) != NULL))) { HTAcceptNode *pres; while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) { if (first) { PUTS("Accept-Charset: "); first=NO; } else PUTC(','); PUTS(HTAtom_name(pres->atom)); if (pres->quality < 1.0 && pres->quality >= 0.0) { sprintf(qstr, ";q=%1.1f", pres->quality); PUTS(qstr); } } } } if (!first) PUTBLOCK(crlf, 2); } if (request_mask & HT_C_ACCEPT_ENC) { int list; HTList *cur; BOOL first=YES; for (list=0; list<2; list++) { if ((!list && ((cur = HTFormat_contentCoding()) != NULL)) || (list && ((cur = HTRequest_encoding(request)) != NULL))) { HTCoding * pres; while ((pres = (HTCoding *) HTList_nextObject(cur))) { double quality = HTCoding_quality(pres); if (first) { PUTS("Accept-Encoding: "); first = NO; } else PUTC(','); PUTS(HTCoding_name(pres)); if (quality < 1.0 && quality >= 0.0) { sprintf(qstr, ";q=%1.1f", quality); PUTS(qstr); } } } } if (!first) PUTBLOCK(crlf, 2); } if (request_mask & HT_C_ACCEPT_TE) { int list; HTList *cur; BOOL first=YES; for (list=0; list<2; list++) { if ((!list && ((cur = HTFormat_transferCoding()) != NULL)) || (list && ((cur = HTRequest_transfer(request)) != NULL))) { HTCoding * pres; while ((pres = (HTCoding *) HTList_nextObject(cur))) { double quality = HTCoding_quality(pres); const char * coding = HTCoding_name(pres); if (first) { PUTS("TE: "); first = NO; } else PUTC(','); /* Special check for "chunked" which is translated to "trailers" */ if (!strcasecomp(coding, "chunked")) PUTS("trailers"); else PUTS(coding); if (quality < 1.0 && quality >= 0.0) { sprintf(qstr, ";q=%1.1f", quality); PUTS(qstr); } } } } if (!first) PUTBLOCK(crlf, 2); } if (request_mask & HT_C_ACCEPT_LAN) { int list; HTList *cur; BOOL first=YES; for (list=0; list<2; list++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -