Klaus Demo bjoern / f9e611f
Cherry-pick string-type related parts of the previously reverted commit Jonas Haag 9 years ago
6 changed file(s) with 31 addition(s) and 41 deletion(s). Raw diff Collapse all Expand all
7272 static PyMethodDef Bjoern_FunctionTable[] = {
7373 {"run", run, METH_VARARGS, run_doc},
7474 {"listen", listen, METH_VARARGS, listen_doc},
75 {NULL, NULL, 0, NULL}
75 {NULL, NULL, 0, NULL}
7676 };
7777
7878 PyMODINIT_FUNC initbjoern()
7979 {
80 _initialize_wsgi_module();
80 PyType_Ready(&StartResponse_Type);
81 assert(StartResponse_Type.tp_flags & Py_TPFLAGS_READY);
8182 _initialize_static_strings();
8283
8384 PyObject* bjoern_module = Py_InitModule("bjoern", Bjoern_FunctionTable);
55 #include <stddef.h>
66 #include <stdbool.h>
77 #include <string.h>
8
9 typedef struct { char* data; size_t len; } string;
810
911 enum http_status { HTTP_BAD_REQUEST = 1, HTTP_LENGTH_REQUIRED, HTTP_SERVER_ERROR };
1012
22 #include "request.h"
33
44 static inline void PyDict_ReplaceKey(PyObject* dict, PyObject* k1, PyObject* k2);
5 static PyObject* wsgi_http_header(Request*, const char*, const size_t);
5 static PyObject* wsgi_http_header(string header);
66 static http_parser_settings parser_settings;
77 static PyObject* wsgi_base_dict = NULL;
88
3333 {
3434 memset(&request->state, 0, sizeof(Request) - (size_t)&((Request*)NULL)->state);
3535 request->state.response_length_unknown = true;
36 request->parser.body = (string){NULL, 0};
3637 }
3738
3839 void Request_free(Request* request)
8788 * [old header data ] ...stuff... [ new header data ]
8889 * ^-------------- A -------------^--------B--------^
8990 *
90 * A = XXX- PARSER->XXX_start
91 * A = XXX- PARSER->XXX.data
9192 * B = len
9293 * A + B = old header start to new header end
9394 */ \
94 do { PARSER->name##_len = (name - PARSER->name##_start) + len; } while(0)
95 do { PARSER->name.len = (name - PARSER->name.data) + len; } while(0)
9596
9697 #define _set_header(k, v) PyDict_SetItem(REQUEST->headers, k, v);
9798 #define _set_header_free_value(k, v) \
112113 static int on_message_begin(http_parser* parser)
113114 {
114115 REQUEST->headers = PyDict_New();
115 PARSER->field_start = NULL;
116 PARSER->field_len = 0;
117 PARSER->value_start = NULL;
118 PARSER->value_len = 0;
116 PARSER->field = (string){NULL, 0};
117 PARSER->value = (string){NULL, 0};
119118 return 0;
120119 }
121120
135134
136135 static int on_header_field(http_parser* parser, const char* field, size_t len)
137136 {
138 if(PARSER->value_start) {
137 if(PARSER->value.data) {
139138 /* Store previous header and start a new one */
140139 _set_header_free_both(
141 wsgi_http_header(REQUEST, PARSER->field_start, PARSER->field_len),
142 PyString_FromStringAndSize(PARSER->value_start, PARSER->value_len)
143 );
144 } else if(PARSER->field_start) {
140 wsgi_http_header(PARSER->field),
141 PyString_FromStringAndSize(PARSER->value.data, PARSER->value.len)
142 );
143 } else if(PARSER->field.data) {
145144 UPDATE_LENGTH(field);
146145 return 0;
147146 }
148 PARSER->field_start = field;
149 PARSER->field_len = len;
150 PARSER->value_start = NULL;
151 PARSER->value_len = 0;
147 PARSER->field = (string){(char*)field, len};
148 PARSER->value = (string){NULL, 0};
152149 return 0;
153150 }
154151
155152 static int
156153 on_header_value(http_parser* parser, const char* value, size_t len)
157154 {
158 if(PARSER->value_start) {
155 if(PARSER->value.data) {
159156 UPDATE_LENGTH(value);
160157 } else {
161158 /* Start a new value */
162 PARSER->value_start = value;
163 PARSER->value_len = len;
159 PARSER->value = (string){(char*)value, len};
164160 }
165161 return 0;
166162 }
168164 static int
169165 on_headers_complete(http_parser* parser)
170166 {
171 if(PARSER->field_start) {
167 if(PARSER->field.data) {
172168 _set_header_free_both(
173 wsgi_http_header(REQUEST, PARSER->field_start, PARSER->field_len),
174 PyString_FromStringAndSize(PARSER->value_start, PARSER->value_len)
169 wsgi_http_header(PARSER->field),
170 PyString_FromStringAndSize(PARSER->value.data, PARSER->value.len)
175171 );
176172 }
177173 return 0;
241237
242238
243239 static PyObject*
244 wsgi_http_header(Request* request, const char* data, size_t len)
245 {
246 PyObject* obj = PyString_FromStringAndSize(NULL, len+strlen("HTTP_"));
240 wsgi_http_header(string header)
241 {
242 PyObject* obj = PyString_FromStringAndSize(NULL, header.len+strlen("HTTP_"));
247243 char* dest = PyString_AS_STRING(obj);
248244
249245 *dest++ = 'H';
252248 *dest++ = 'P';
253249 *dest++ = '_';
254250
255 while(len--) {
256 char c = *data++;
251 while(header.len--) {
252 char c = *header.data++;
257253 if(c == '-')
258254 *dest++ = '_';
259255 else if(c >= 'a' && c <= 'z')
1818
1919 typedef struct {
2020 http_parser parser;
21 const char* field_start;
22 size_t field_len;
23 const char* value_start;
24 size_t value_len;
21 string field;
22 string value;
23 string body;
2524 } bj_parser;
2625
2726 typedef struct {
1919 bool
2020 wsgi_call_application(Request* request)
2121 {
22 assert(StartResponse_Type.tp_flags & Py_TPFLAGS_READY);
2322 StartResponse* start_response = PyObject_NEW(StartResponse, &StartResponse_Type);
2423 start_response->request = request;
2524
378377 assert(new_chunk_p == PyString_AS_STRING(new_chunk) + n + chunklen + 1);
379378 return new_chunk;
380379 }
381
382 void _initialize_wsgi_module() {
383 int ready = PyType_Ready(&StartResponse_Type);
384 assert(ready == 0);
385 assert(StartResponse_Type.tp_flags & Py_TPFLAGS_READY);
386 }
00 #include <Python.h>
11 #include "request.h"
22
3 void _initialize_wsgi_module();
43 bool wsgi_call_application(Request*);
54 PyObject* wsgi_iterable_get_next_chunk(Request*);
65 PyObject* wrap_http_chunk_cruft_around(PyObject* chunk);