Annotation of libwww/Library/src/HTTPRes.c, revision 2.4
2.1 frystyk 1: /* HTTPRes.c
2.4 ! frystyk 2: ** HTTP RESPONSE GENERATION
2.1 frystyk 3: **
4: ** This module implements the output stream for HTTP used for sending
5: ** responces with or without a entity body. It is the server equivalent
6: ** to the HTTPReq module
7: **
8: ** History:
9: ** Dec 95 HFN Written from scratch
10: */
11:
12: /* Library Includes */
13: #include "tcp.h"
14: #include "HTUtils.h"
15: #include "HTString.h"
16: #include "HTWWWStr.h"
17: #include "HTAccess.h"
18: #include "HTWriter.h"
2.4 ! frystyk 19: #include "HTFWrite.h"
2.1 frystyk 20: #include "HTEvntrg.h"
21: #include "HTNetMan.h"
22: #include "HTReqMan.h"
2.4 ! frystyk 23: #include "HTTPGen.h"
2.1 frystyk 24: #include "HTTPUtil.h"
25: #include "HTTPRes.h" /* Implements */
26:
27: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
28:
29: struct _HTStream {
30: CONST HTStreamClass * isa;
31: HTStream * target;
32: HTRequest * request;
33: BOOL transparent;
34: };
35:
36: /* ------------------------------------------------------------------------- */
37: /* HTTP Output Request Stream */
38: /* ------------------------------------------------------------------------- */
39:
40: /* HTTPMakeResponse
41: ** ----------------
42: ** Makes a HTTP/1.0-1.1 response header.
43: */
2.4 ! frystyk 44: PRIVATE int HTTPMakeResponse (HTStream * me, HTRequest * request)
2.1 frystyk 45: {
46: char linebuf[256];
47: if (request->error_stack) {
48:
49: /* @@@ WRITE A SMALL HTError_response() function */
50: sprintf(linebuf, "HTTP/1.0 404 Not Found%c%c", CR, LF);
51:
52: PUTBLOCK(linebuf, (int) strlen(linebuf));
53: } else {
54: sprintf(linebuf, "HTTP/1.0 200 OK%c%c", CR, LF);
55: PUTBLOCK(linebuf, (int) strlen(linebuf));
56:
57: /* Response Headers */
58: if (request->ResponseMask & HT_S_SERVER) {
59: sprintf(linebuf, "Server: %s/%s %s/%s%c%c",
60: HTLib_appName(), HTLib_appVersion(),
61: HTLib_name(), HTLib_version(), CR, LF);
62: PUTBLOCK(linebuf, (int) strlen(linebuf));
63: }
64: }
2.4 ! frystyk 65: if(PROT_TRACE)TTYPrint(TDEST,"HTTP........ Generating Response Headers\n");
! 66: return HT_OK;
2.1 frystyk 67: }
68:
69: PRIVATE int HTTPResponse_put_block (HTStream * me, CONST char * b, int l)
70: {
2.4 ! frystyk 71: if (me->target) {
! 72: if (me->transparent)
! 73: return PUTBLOCK(b, l);
! 74: else {
! 75: HTTPMakeResponse(me, me->request); /* Generate header */
! 76: me->transparent = YES;
! 77: return b ? PUTBLOCK(b, l) : HT_OK;
! 78: }
2.1 frystyk 79: }
2.4 ! frystyk 80: return HT_WOULD_BLOCK;
2.1 frystyk 81: }
82:
83: PRIVATE int HTTPResponse_put_character (HTStream * me, char c)
84: {
85: return HTTPResponse_put_block(me, &c, 1);
86: }
87:
88: PRIVATE int HTTPResponse_put_string (HTStream * me, CONST char * s)
89: {
90: return HTTPResponse_put_block(me, s, strlen(s));
91: }
92:
93: /*
94: ** Flushes data but doesn't free stream object
95: */
96: PRIVATE int HTTPResponse_flush (HTStream * me)
97: {
2.4 ! frystyk 98: if (!me->transparent) {
! 99: int status = HTTPMakeResponse(me, me->request);
! 100: if (status != HT_OK) return status;
! 101: }
! 102: return (*me->target->isa->flush)(me->target);
2.1 frystyk 103: }
104:
105: /*
106: ** Flushes data and frees stream object
107: */
108: PRIVATE int HTTPResponse_free (HTStream * me)
109: {
2.4 ! frystyk 110: TTYPrint(TDEST, "TESTTESTTEST FREEING RESPONSE STREAM\n");
! 111: if (me->target) {
! 112: int status;
! 113: if (!me->transparent)
! 114: if ((status = HTTPMakeResponse(me, me->request)) != HT_OK)
! 115: return status;
! 116: if ((status = (*me->target->isa->_free)(me->target)) != HT_OK)
! 117: return status;
2.1 frystyk 118: }
2.4 ! frystyk 119: return HT_OK;
2.1 frystyk 120: }
121:
122: PRIVATE int HTTPResponse_abort (HTStream * me, HTList * e)
123: {
124: if (me->target) (*me->target->isa->abort)(me->target, e);
125: if (PROT_TRACE) TTYPrint(TDEST, "HTTPResponse ABORTING...\n");
126: return HT_ERROR;
127: }
128:
129: /* HTTPResponse Stream
130: ** -----------------
131: */
132: PRIVATE CONST HTStreamClass HTTPResponseClass =
133: {
134: "HTTPResponse",
135: HTTPResponse_flush,
136: HTTPResponse_free,
137: HTTPResponse_abort,
138: HTTPResponse_put_character,
139: HTTPResponse_put_string,
140: HTTPResponse_put_block
141: };
142:
2.4 ! frystyk 143: /*
! 144: ** This stream is responsible for generating a full HTTP/1.x response. It
! 145: ** may either do so by forwarding a response directly from an origin
! 146: ** server (if we are proxying) - or it can generate the response itself.
! 147: */
! 148: PUBLIC HTStream * HTTPResponse_new (HTRequest * request,
! 149: void * param,
! 150: HTFormat input_format,
! 151: HTFormat output_format,
! 152: HTStream * output_stream)
! 153: {
! 154: HTStream * me = NULL;
! 155: HTdns * dns;
! 156: if (!request || !request->net) return HTErrorStream();
! 157: /*
! 158: ** If we have a HTTP 1.x response then forward untouched
! 159: */
! 160: if ((dns = request->net->dns)) {
! 161: char * s_class = HTDNS_serverClass(dns);
! 162: int version = HTDNS_serverVersion(dns);
! 163: /* We are not using the version info for the moment */
! 164: if (s_class && !strcasecomp(s_class, "http")) {
! 165: if (STREAM_TRACE) TTYPrint(TDEST, "HTTPResponse Direct output\n");
! 166: return output_stream;
! 167: }
! 168: }
! 169: if ((me = (HTStream *) calloc(1, sizeof(HTStream))) == NULL)
! 170: outofmem(__FILE__, "HTTPResponse_new");
2.1 frystyk 171: me->isa = &HTTPResponseClass;
2.4 ! frystyk 172: me->target = output_stream;
2.1 frystyk 173: me->request = request;
2.4 ! frystyk 174:
! 175: TTYPrint(TDEST, "TESTTESTTEST CREATING RESPONSE STREAM\n");
! 176:
! 177: /* Here we should also check whether we have content length etc. */
! 178:
! 179: return me;
2.1 frystyk 180: }
Webmaster