summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_php_sapi.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nxt_php_sapi.c225
1 files changed, 146 insertions, 79 deletions
diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c
index b57d5c8f..1535d56d 100644
--- a/src/nxt_php_sapi.c
+++ b/src/nxt_php_sapi.c
@@ -56,6 +56,8 @@ static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC);
static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC);
#endif
+static void nxt_php_flush(void *server_context);
+
extern nxt_int_t nxt_php_sapi_init(nxt_thread_t *thr, nxt_runtime_t *rt);
@@ -71,7 +73,7 @@ static sapi_module_struct nxt_php_sapi_module =
NULL, /* deactivate */
nxt_php_unbuffered_write, /* unbuffered write */
- NULL, /* flush */
+ nxt_php_flush, /* flush */
NULL, /* get uid */
NULL, /* getenv */
@@ -238,16 +240,28 @@ nxt_php_read_request(nxt_task_t *task, nxt_app_rmsg_t *rmsg,
{
u_char *p;
size_t s;
+ nxt_int_t rc;
nxt_str_t script_name;
nxt_app_request_header_t *h;
h = &ctx->r.header;
- nxt_app_msg_read_str(task, rmsg, &h->method);
- nxt_app_msg_read_str(task, rmsg, &h->target);
- nxt_app_msg_read_str(task, rmsg, &h->path);
+#define RC(S) \
+ do { \
+ rc = (S); \
+ if (nxt_slow_path(rc != NXT_OK)) { \
+ goto fail; \
+ } \
+ } while(0)
- nxt_app_msg_read_size(task, rmsg, &s);
+#define NXT_READ(dst) \
+ RC(nxt_app_msg_read_str(task, rmsg, (dst)))
+
+ NXT_READ(&h->method);
+ NXT_READ(&h->target);
+ NXT_READ(&h->path);
+
+ RC(nxt_app_msg_read_size(task, rmsg, &s));
if (s > 0) {
s--;
h->query.start = h->target.start + s;
@@ -293,19 +307,29 @@ nxt_php_read_request(nxt_task_t *task, nxt_app_rmsg_t *rmsg,
ctx->script = nxt_php_path;
}
- nxt_app_msg_read_str(task, rmsg, &h->version);
+ NXT_READ(&h->version);
- nxt_app_msg_read_str(task, rmsg, &h->cookie);
- nxt_app_msg_read_str(task, rmsg, &h->content_type);
- nxt_app_msg_read_str(task, rmsg, &h->content_length);
+ NXT_READ(&ctx->r.remote);
- nxt_app_msg_read_size(task, rmsg, &s);
+ NXT_READ(&h->host);
+ NXT_READ(&h->cookie);
+ NXT_READ(&h->content_type);
+ NXT_READ(&h->content_length);
+
+ RC(nxt_app_msg_read_size(task, rmsg, &s));
h->parsed_content_length = s;
- nxt_app_msg_read_str(task, rmsg, &ctx->r.body.preread);
+ NXT_READ(&ctx->r.body.preread);
+
+#undef NXT_READ
+#undef RC
/* Further headers read moved to nxt_php_register_variables. */
return NXT_OK;
+
+fail:
+
+ return rc;
}
@@ -357,6 +381,9 @@ nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
// SCRIPT_FILENAME
// DOCUMENT_ROOT
+ NXT_WRITE(&r->remote);
+
+ NXT_WRITE(&h->host);
NXT_WRITE(&h->cookie);
NXT_WRITE(&h->content_type);
NXT_WRITE(&h->content_length);
@@ -390,6 +417,7 @@ static nxt_int_t
nxt_php_run(nxt_task_t *task,
nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg)
{
+ nxt_int_t rc;
zend_file_handle file_handle;
nxt_php_run_ctx_t run_ctx;
nxt_app_request_header_t *h;
@@ -408,7 +436,11 @@ nxt_php_run(nxt_task_t *task,
h = &run_ctx.r.header;
- nxt_php_read_request(task, rmsg, &run_ctx);
+ rc = nxt_php_read_request(task, rmsg, &run_ctx);
+
+ if (nxt_slow_path(rc != NXT_OK)) {
+ goto fail;
+ }
SG(server_context) = &run_ctx;
SG(request_info).request_uri = (char *) h->target.start;
@@ -465,7 +497,11 @@ nxt_php_write(nxt_php_run_ctx_t *ctx, const u_char *data, size_t len,
{
nxt_int_t rc;
- rc = nxt_app_msg_write_raw(ctx->task, ctx->wmsg, data, len);
+ if (len > 0) {
+ rc = nxt_app_msg_write_raw(ctx->task, ctx->wmsg, data, len);
+ } else {
+ rc = NXT_OK;
+ }
if (flush || last) {
rc = nxt_app_msg_flush(ctx->task, ctx->wmsg, last);
@@ -490,13 +526,31 @@ static int
nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC)
#endif
{
+ nxt_int_t rc;
nxt_php_run_ctx_t *ctx;
ctx = SG(server_context);
- nxt_php_write(ctx, (u_char *) str, str_length, 1, 0);
+ rc = nxt_php_write(ctx, (u_char *) str, str_length, 1, 0);
- return str_length;
+ if (nxt_fast_path(rc == NXT_OK)) {
+ return str_length;
+ }
+
+ // TODO handle NXT_AGAIN
+ php_handle_aborted_connection();
+ return 0;
+}
+
+
+static void
+nxt_php_flush(void *server_context)
+{
+ nxt_php_run_ctx_t *ctx;
+
+ ctx = server_context;
+
+ (void) nxt_app_msg_flush(ctx->task, ctx->wmsg, 0);
}
@@ -504,10 +558,11 @@ static int
nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
size_t len;
+ u_char *status, buf[64];
+ nxt_int_t rc;
+ nxt_php_run_ctx_t *ctx;
sapi_header_struct *h;
zend_llist_position zpos;
- u_char *status, buf[4096];
- nxt_php_run_ctx_t *ctx;
static const u_char default_repsonse[]
= "HTTP/1.1 200 OK\r\n"
@@ -526,47 +581,61 @@ nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
ctx = SG(server_context);
+#define RC(S) \
+ do { \
+ rc = (S); \
+ if (nxt_slow_path(rc != NXT_OK)) { \
+ goto fail; \
+ } \
+ } while(0)
+
if (SG(request_info).no_headers == 1) {
- nxt_php_write(ctx, default_repsonse, sizeof(default_repsonse) - 1,
- 1, 0);
+ RC(nxt_php_write(ctx, default_repsonse, sizeof(default_repsonse) - 1,
+ 1, 0));
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
- nxt_php_write(ctx, http_11, sizeof(http_11) - 1, 0, 0);
-
if (SG(sapi_headers).http_status_line) {
- status = (u_char *) SG(sapi_headers).http_status_line + 9;
+ status = (u_char *) SG(sapi_headers).http_status_line;
len = nxt_strlen(status);
- nxt_php_write(ctx, status, len, 0, 0);
+ RC(nxt_php_write(ctx, status, len, 0, 0));
} else if (SG(sapi_headers).http_response_code) {
status = nxt_sprintf(buf, buf + sizeof(buf), "%03d",
SG(sapi_headers).http_response_code);
len = status - buf;
- nxt_php_write(ctx, buf, len, 0, 0);
+ RC(nxt_php_write(ctx, http_11, sizeof(http_11) - 1, 0, 0));
+ RC(nxt_php_write(ctx, buf, len, 0, 0));
} else {
- nxt_php_write(ctx, _200_ok, sizeof(_200_ok) - 1, 0, 0);
+ RC(nxt_php_write(ctx, http_11, sizeof(http_11) - 1, 0, 0));
+ RC(nxt_php_write(ctx, _200_ok, sizeof(_200_ok) - 1, 0, 0));
}
- nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 0, 0);
-
- nxt_php_write(ctx, default_headers, sizeof(default_headers) - 1, 0, 0);
+ RC(nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 0, 0));
+ RC(nxt_php_write(ctx, default_headers, sizeof(default_headers) - 1, 0, 0));
h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos);
while (h) {
- nxt_php_write(ctx, (u_char *) h->header, h->header_len, 0, 0);
- nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 0, 0);
+ RC(nxt_php_write(ctx, (u_char *) h->header, h->header_len, 0, 0));
+ RC(nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 0, 0));
h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos);
}
- nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 1, 0);
+ RC(nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 1, 0));
+
+#undef RC
return SAPI_HEADER_SENT_SUCCESSFULLY;
+
+fail:
+
+ // TODO handle NXT_AGAIN
+ return SAPI_HEADER_SEND_FAILED;
}
@@ -659,12 +728,17 @@ nxt_php_read_cookies(TSRMLS_D)
static void
nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
{
+ u_char *colon;
nxt_str_t n, v;
nxt_int_t rc;
+ nxt_str_t host, server_name, server_port;
nxt_task_t *task;
nxt_php_run_ctx_t *ctx;
nxt_app_request_header_t *h;
+ static nxt_str_t def_host = nxt_string("localhost");
+ static nxt_str_t def_port = nxt_string("80");
+
ctx = SG(server_context);
h = &ctx->r.header;
@@ -672,9 +746,11 @@ nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
nxt_debug(task, "php register variables");
- php_register_variable_safe((char *) "SERVER_PROTOCOL",
- (char *) h->version.start,
- h->version.length, track_vars_array TSRMLS_CC);
+#define NXT_PHP_SET(n, v) \
+ php_register_variable_safe((char *) (n), (char *) (v).start, \
+ (v).length, track_vars_array TSRMLS_CC) \
+
+ NXT_PHP_SET("SERVER_PROTOCOL", h->version);
/*
* 'SCRIPT_NAME'
@@ -705,62 +781,53 @@ nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
* If PHP is running as a command-line processor this variable contains the
* script name since PHP 4.3.0. Previously it was not available.
*/
- php_register_variable_safe((char *) "PHP_SELF",
- (char *) nxt_php_script.start,
- nxt_php_script.length,
- track_vars_array TSRMLS_CC);
-
- php_register_variable_safe((char *) "SCRIPT_NAME",
- (char *) nxt_php_script.start,
- nxt_php_script.length,
- track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("PHP_SELF", nxt_php_script);
+ NXT_PHP_SET("SCRIPT_NAME", nxt_php_script);
} else {
- php_register_variable_safe((char *) "PHP_SELF",
- (char *) h->path.start,
- h->path.length, track_vars_array TSRMLS_CC);
-
- php_register_variable_safe((char *) "SCRIPT_NAME",
- (char *) h->path.start,
- h->path.length, track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("PHP_SELF", h->path);
+ NXT_PHP_SET("SCRIPT_NAME", h->path);
}
- php_register_variable_safe((char *) "SCRIPT_FILENAME",
- (char *) ctx->script.start,
- ctx->script.length,
- track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("SCRIPT_FILENAME", ctx->script);
+ NXT_PHP_SET("DOCUMENT_ROOT", nxt_php_root);
- php_register_variable_safe((char *) "DOCUMENT_ROOT",
- (char *) nxt_php_root.start,
- nxt_php_root.length,
- track_vars_array TSRMLS_CC);
-
- php_register_variable_safe((char *) "REQUEST_METHOD",
- (char *) h->method.start,
- h->method.length, track_vars_array TSRMLS_CC);
-
- php_register_variable_safe((char *) "REQUEST_URI",
- (char *) h->target.start,
- h->target.length, track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("REQUEST_METHOD", h->method);
+ NXT_PHP_SET("REQUEST_URI", h->target);
if (h->query.start != NULL) {
- php_register_variable_safe((char *) "QUERY_STRING",
- (char *) h->query.start,
- h->query.length, track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("QUERY_STRING", h->query);
}
if (h->content_type.start != NULL) {
- php_register_variable_safe((char *) "CONTENT_TYPE",
- (char *) h->content_type.start,
- h->content_type.length, track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("CONTENT_TYPE", h->content_type);
}
if (h->content_length.start != NULL) {
- php_register_variable_safe((char *) "CONTENT_LENGTH",
- (char *) h->content_length.start,
- h->content_length.length,
- track_vars_array TSRMLS_CC);
+ NXT_PHP_SET("CONTENT_LENGTH", h->content_length);
+ }
+
+ host = h->host;
+ if (host.length == 0) {
+ host = def_host;
}
+ server_name = host;
+ colon = nxt_memchr(host.start, ':', host.length);
+
+ if (colon != NULL) {
+ server_name.length = colon - host.start;
+
+ server_port.start = colon + 1;
+ server_port.length = host.length - server_name.length - 1;
+ } else {
+ server_port = def_port;
+ }
+
+ NXT_PHP_SET("SERVER_NAME", server_name);
+ NXT_PHP_SET("SERVER_PORT", server_port);
+
+ NXT_PHP_SET("REMOTE_ADDR", ctx->r.remote);
+
while (nxt_app_msg_read_str(task, ctx->rmsg, &n) == NXT_OK) {
if (nxt_slow_path(n.length == 0)) {
break;
@@ -771,10 +838,10 @@ nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
break;
}
- php_register_variable_safe((char *) n.start,
- (char *) v.start, v.length,
- track_vars_array TSRMLS_CC);
+ NXT_PHP_SET(n.start, v);
}
+
+#undef NXT_PHP_SET
}