📄 http.c
字号:
HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_CONFLICT, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = HT_CONFLICT; break; case 410: /* Gone */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_GONE, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -410; break; case 411: /* Length Required */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_LENGTH_REQUIRED, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = HT_LENGTH_REQUIRED; break; case 412: /* Precondition failed */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_PRECON_FAILED, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -412; break; case 413: /* Request entity too large */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_TOO_BIG, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -413; break; case 414: /* Request-URI too long */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_URI_TOO_BIG, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -414; break; case 415: /* Unsupported */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_UNSUPPORTED, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -415; break; case 416: /* Request Range not satisfiable */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_BAD_RANGE, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -416; break; case 417: /* Expectation Failed */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_EXPECTATION_FAILED, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -417; break; case 418: /* Reauthentication required */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_REAUTH, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -418; break; case 419: /* Proxy Reauthentication required */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_PROXY_REAUTH, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -419; break; default: HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_BAD_REQUEST, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -400; break; } break; case 5: switch (me->status) { case 501: HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_NOT_IMPLEMENTED, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -501; break; case 502: HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_BAD_GATE, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -502; break; case 503: HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_DOWN, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; /* ** If Retry-After header is found then return HT_RETRY else HT_ERROR. ** The caller may want to reissue the request at a later point in time. */ { HTResponse * response = HTRequest_response(me->request); if (HTResponse_retryTime(response)) http->result = HT_RETRY; else http->result = -500; } break; case 504: HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_GATE_TIMEOUT, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -504; break; case 505: /* Unsupported protocol version */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_BAD_VERSION, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = HT_BAD_VERSION; break; case 506: /* Partial update Not Implemented */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_NO_PARTIAL_UPDATE, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = HT_BAD_VERSION; break; default: /* bad number */ HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_INTERNAL, me->reason, (int) strlen(me->reason), "HTTPNextState"); http->next = HTTP_ERROR; http->result = -500; break; } break; default: HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_BAD_REPLY, (void *) me->buffer, me->buflen, "HTTPNextState"); http->next = HTTP_ERROR; http->result = -(me->status); break; }}/* ------------------------------------------------------------------------- *//* HTTP Status Line Stream *//* ------------------------------------------------------------------------- *//*** Analyze the stream we have read. If it is a HTTP 1.0 or higher** then create a MIME-stream, else create a Guess stream to find out** what the 0.9 server is sending. We need to copy the buffer as we don't** know if we can modify the contents or not.**** Stream handling is a function of the status code returned from the ** server:** 200: Use `output_stream' in HTRequest structure** else: Use `debug_stream' in HTRequest structure**** Return: YES if buffer should be written out. NO otherwise*/PRIVATE int stream_pipe (HTStream * me, int length){ HTRequest * request = me->request; HTNet * net = HTRequest_net(request); HTHost * host = HTNet_host(net);#if 0 { char * uri = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); fprintf(stderr, "HTTP header: %s for '%s'\n", me->buffer, uri); HT_FREE(uri); }#endif /* ** Just check for HTTP and not HTTP/ as NCSA server chokes on 1.1 replies ** Thanks to Markku Savela <msa@msa.tte.vtt.fi> */ if (strncasecomp(me->buffer, "http", 4)) { int status; HTRequest_addError(request, ERR_INFO, NO, HTERR_HTTP09, (void *) me->buffer, me->buflen, "HTTPStatusStream"); me->target = HTStreamStack(WWW_UNKNOWN, HTRequest_outputFormat(request), HTRequest_outputStream(request), request, NO); me->http->next = HTTP_OK; if ((status = PUTBLOCK(me->buffer, me->buflen)) == HT_OK) me->transparent = YES; HTHost_setVersion(host, HTTP_09); if (length > 0) HTHost_setConsumed(host, length); HTTRACE(PROT_TRACE, "HTTP Status. `%s\' is probably a broken 1.0 server that doesn't understand HEAD\n" _ HTHost_name(host)); return HT_ERROR; } else { HTResponse * response = HTRequest_response(request); char * ptr = me->buffer+5; /* Skip the HTTP part */ char * vptr = NULL; int major = 0; int minor = 0; me->version = vptr = HTNextField(&ptr); if (vptr) { major = (int) strtol(me->version, &vptr, 10); if (vptr++) minor = strtol(vptr, NULL, 10); } /* Here we want to find out when to use persistent connection */ if (major > 1 && major < 100) { HTTRACE(PROT_TRACE, "HTTP Status. Major version number is %d\n" _ major); me->target = HTErrorStream(); me->status = 9999; HTTPNextState(me); /* Get next state */ return HT_ERROR; } else if (minor <= 0) { if (major > 100) { HTTRACE(PROT_TRACE, "HTTP Status. This is a *BROKEN* HTTP/1.0 server\n"); me->status = 200; } else { HTTRACE(PROT_TRACE, "HTTP Status. This is an HTTP/1.0 server\n"); me->status = atoi(HTNextField(&ptr)); } HTHost_setVersion(host, HTTP_10); } else { /* 1.x, x>0 family */ HTHost_setVersion(host, HTTP_11); /* Best we can do */ if (ConnectionMode & HTTP_11_NO_PIPELINING) { HTTRACE(PROT_TRACE, "HTTP........ Mode is HTTP/1.1 with NO PIPELINING\n"); HTNet_setPersistent(net, YES, HT_TP_SINGLE); } else if (ConnectionMode & HTTP_11_MUX) { HTTRACE(PROT_TRACE, "HTTP........ Mode is HTTP/1.1 with MUXING\n"); HTNet_setPersistent(net, YES, HT_TP_INTERLEAVE); } else if (ConnectionMode & HTTP_FORCE_10) { HTTRACE(PROT_TRACE, "HTTP........ Mode is FORCE HTTP/1.0\n"); HTHost_setVersion(host, HTTP_10); HTNet_setPersistent(net, NO, HT_TP_SINGLE); } else HTNet_setPersistent(net, YES, HT_TP_PIPELINE); me->status = atoi(HTNextField(&ptr)); } me->reason = ptr; if ((ptr = strchr(me->reason, '\r')) != NULL) /* Strip \r and \n */ *ptr = '\0'; else if ((ptr = strchr(me->reason, '\n')) != NULL) *ptr = '\0'; /* ** If it is a 1xx code then find out what to do and return until we ** get the next code. In the case of Upgrade we may not get back here ** at all. If we are uploading an entity then continue doing that */ if (me->status/100 == 1) { if (HTTPInformation(me) == YES) { me->buflen = 0; me->state = EOL_BEGIN; if (me->info_target) (*me->info_target->isa->_free)(me->info_target); me->info_target = HTStreamStack(WWW_MIME_CONT, HTRequest_debugFormat(request), HTRequest_debugStream(request), request, NO); if (length > 0) HTHost_setConsumed(host, length); return HT_OK; } } /* ** As we are getting fresh metainformation in the HTTP response, ** we clear the old metainfomation in order not to mix it with the new ** one. This is particularly important for the content-length and the ** like. The TRACE and OPTIONS method just adds to the current ** metainformation so in that case we don't clear the anchor. */ if (me->status==200 || me->status==203 || me->status==300) { /* ** 200, 203 and 300 are all fully cacheable responses. No byte ** ranges or anything else make life hard in this case. */ HTAnchor_clearHeader(HTRequest_anchor(request)); HTResponse_setCachable(response, HT_CACHE_ALL); me->target = HTStreamStack(WWW_MIME, HTRequest_outputFormat(request), HTRequest_outputStream(request), request, NO); } else if (me->status==204) { HTResponse_setCachable(response, HT_CACHE_ALL); me->target = HTStreamStack(WWW_MIME_HEAD, HTRequest_debugFormat(request), HTRequest_debugStream(request), request, NO); } else if (me->status==206) { /* ** We got a partial response and now we must check whether ** we issued a cache If-Range request or it was a new ** partial response which we don't have in cache. In the latter ** case, we don't cache the object and in the former we append ** the result to the already existing cache entry. */ HTReload reload = HTRequest_reloadMode(request); if (reload == HT_CACHE_RANGE_VALIDATE) { HTResponse_setCachable(response, HT_CACHE_ALL); me->target = HTStreamStack(WWW_MIME_PART, HTRequest_outputFormat(request), HTRequest_outputStream(request), request, NO); } else { HTAnchor_clearHeader(HTRequest_anchor(request)); me->target = HTStreamStack(WWW_MIME, HTRequest_outputFormat(request), HTRequest_outputStream(request), request, NO); } } else if (me->status==304) { HTResponse_setCachable(response, HT_CACHE_NOT_MODIFIED); me->target = HTStreamStack(WWW_MIME_HEAD, HTRequest_debugFormat(request), HTRequest_debugStream(request), request, NO); } else if (HTRequest_debugStream(request)) { HTResponse_setCachable(response, (me->status == 201) ? HT_CACHE_ETAG : HT_NO_CACHE); me->target = HTStreamStack(WWW_MIME, HTRequest_debugFormat(request), HTRequest_debugStream(request), request, NO); } else { /* ** We still need to parse the MIME part in order to find any ** valuable meta information which is needed from the response. */ HTResponse_setCachable(response, (me->status == 201) ? HT_CACHE_ETAG : HT_NO_CACHE); me->target = HTStreamStack(WWW_MIME, HTRequest_debugFormat(request), HTRequest_debugStream(request), request, NO); } } if (!me->target) me->target = HTErrorStream(); HTTPNextState(me); /* Get next state */ me->transparent = YES; if (length > 0) HTHost_setConsumed(HTNet_host(HTRequest_net(me->request)), length); return HT_OK;}/*** Searches for HTTP header line until buffer fills up or a CRLF or LF** is found*/PRIVATE int HTTPStatus_put_block (HTStream * me, const char * b, int l){ int status = HT_OK; int length = l; me->startLen = me->buflen; while (!me->transparent && l-- > 0) { if (me->info_target) { /* Put data down the 1xx return code parser until we are done. */ status = (*me->info_target->isa->put_block)(me->info_target, b, l+1); if (status != HT_CONTINUE) return status; /* Now free the info stream */ (*me->info_target->isa->_free)(me->info_target); me->info_target = NULL; /* Update where we are in the stream */ l = HTHost_remainingRead(HTNet_host(HTRequest_net(me->request))); b += (length-l); length = l; if (l <= 0) break; } else { *(me->buffer+me->buflen++) = *b; if (me->state == EOL_FCR) { if (*b == LF) { /* Line found */ if ((status = stream_pipe(me, length-l)) != HT_OK) return status; } else { me->state = EOL_BEGIN; } } else if (*b == CR) { me->state = EOL_FCR; } else if (*b == LF) { if ((status = stream_pipe(me, length-l)) != HT_OK) return status; } else { if (me->buflen >= MAX_STATUS_LEN) { if ((status = stream_pipe(me, length-l)) != HT_OK) return status; } } b++; } } if (!me->transparent && length != l) HTHost_setConsumed(HTNet_host(HTRequest_net(me->request)), length-l); if (l > 0) return PUTBLOCK(b, l); return status;}PRIVATE int HTTPStatus_put_string (HTStream * me, const char * s){ return HTTPStatus_put_block(me, s, (int) strlen(s));}PRIVATE int HTTPStatus_put_character (HTStream * me, char c){ return HTTPStatus_put_block(me, &c, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -