示例#1
0
文件: cache.c 项目: ni-webtech/http
/*
    See if there is acceptable cached content for this request. If so, return true.
    Will setup tx->cacheBuffer as a side-effect if the output should be captured and cached.
 */
static bool fetchCachedResponse(HttpConn *conn)
{
    HttpTx      *tx;
    MprTime     modified, when;
    cchar       *value, *key, *tag;
    int         status, cacheOk, canUseClientCache;

    tx = conn->tx;

    /*
        Transparent caching. Manual caching must manually call httpWriteCached()
     */
    key = makeCacheKey(conn);
    if ((value = httpGetHeader(conn, "Cache-Control")) != 0 && 
            (scontains(value, "max-age=0") == 0 || scontains(value, "no-cache") == 0)) {
        mprLog(3, "Client reload. Cache-control header '%s' rejects use of cached content.", value);

    } else if ((tx->cachedContent = mprReadCache(conn->host->responseCache, key, &modified, 0)) != 0) {
        /*
            See if a NotModified response can be served. This is much faster than sending the response.
            Observe headers:
                If-None-Match: "ec18d-54-4d706a63"
                If-Modified-Since: Fri, 04 Mar 2012 04:28:19 GMT
            Set status to OK when content must be transmitted.
         */
        cacheOk = 1;
        canUseClientCache = 0;
        tag = mprGetMD5(key);
        if ((value = httpGetHeader(conn, "If-None-Match")) != 0) {
            canUseClientCache = 1;
            if (scmp(value, tag) != 0) {
                cacheOk = 0;
            }
        }
        if (cacheOk && (value = httpGetHeader(conn, "If-Modified-Since")) != 0) {
            canUseClientCache = 1;
            mprParseTime(&when, value, 0, 0);
            if (modified > when) {
                cacheOk = 0;
            }
        }
        status = (canUseClientCache && cacheOk) ? HTTP_CODE_NOT_MODIFIED : HTTP_CODE_OK;
        mprLog(3, "cacheHandler: Use cached content for %s, status %d", key, status);
        httpSetStatus(conn, status);
        httpSetHeader(conn, "Etag", mprGetMD5(key));
        httpSetHeader(conn, "Last-Modified", mprFormatUniversalTime(MPR_HTTP_DATE, modified));
        return 1;
    }
    mprLog(3, "cacheHandler: No cached content for %s", key);
    return 0;
}
示例#2
0
文件: http.c 项目: adammendoza/http
static void readBody(HttpConn *conn, MprFile *outFile)
{
    char        buf[BIT_MAX_BUFFER];
    cchar       *result;
    ssize       bytes;

    while (!conn->error && conn->sock && (bytes = httpRead(conn, buf, sizeof(buf))) > 0) {
        if (!app->noout) {
            result = formatOutput(conn, buf, &bytes);
            if (result) {
                mprWriteFile(outFile, result, bytes);
            }
        }
#if FUTURE
        //  This should be pushed into a range filter.
        //  Buffer all output and then parsing can work
        type = httpGetHeader(conn, "Content-Type");
        if (scontains(type, "multipart/byteranges")) {
            if ((boundary = scontains(type, "boundary=")) != 0) {
                boundary += 9;
                if (*boundary) {
                    boundary = sfmt("--%s\r\n", boundary);
                }
            }
        }
#endif
    }
}
示例#3
0
文件: tx.c 项目: adammendoza/http
static void setCorsHeaders(HttpConn *conn)
{
    HttpRoute   *route;
    cchar       *origin;

    route = conn->rx->route;

    /*
        Cannot use wildcard origin response if allowing credentials
     */
    if (*route->corsOrigin && !route->corsCredentials) {
        httpSetHeaderString(conn, "Access-Control-Allow-Origin", route->corsOrigin);
    } else {
        origin = httpGetHeader(conn, "Origin");
        httpSetHeaderString(conn, "Access-Control-Allow-Origin", origin ? origin : "*");
    }
    if (route->corsCredentials) {
        httpSetHeaderString(conn, "Access-Control-Allow-Credentials", "true");
    }
    if (route->corsHeaders) {
        httpSetHeaderString(conn, "Access-Control-Allow-Headers", route->corsHeaders);
    }
    if (route->corsMethods) {
        httpSetHeaderString(conn, "Access-Control-Allow-Methods", route->corsMethods);
    }
    if (route->corsAge) {
        httpSetHeader(conn, "Access-Control-Max-Age", "%d", route->corsAge);
    }
}
示例#4
0
文件: ejsHttp.c 项目: soffmodd/ejs-2
static EjsString *getStringHeader(Ejs *ejs, EjsHttp *hp, cchar *key)
{
    cchar       *value;

    if (!waitForResponseHeaders(hp)) {
        return 0;
    }
    value = httpGetHeader(hp->conn, key);
    if (value == 0) {
        return ESV(null);
    }
    return ejsCreateStringFromAsc(ejs, value);
}
示例#5
0
文件: ejsHttp.c 项目: soffmodd/ejs-2
static EjsDate *getDateHeader(Ejs *ejs, EjsHttp *hp, cchar *key)
{
    MprTime     when;
    cchar       *value;

    if (!waitForResponseHeaders(hp)) {
        return 0;
    }
    value = httpGetHeader(hp->conn, key);
    if (value == 0) {
        return ESV(null);
    }
    if (mprParseTime(&when, value, MPR_UTC_TIMEZONE, NULL) < 0) {
        value = 0;
    }
    return ejsCreateDate(ejs, when);
}
示例#6
0
文件: ejsHttp.c 项目: soffmodd/ejs-2
/*  
    function header(key: String): String
 */
static EjsString *http_header(Ejs *ejs, EjsHttp *hp, int argc, EjsObj **argv)
{
    EjsString   *result;
    cchar       *value;
    char        *str;

    if (!waitForResponseHeaders(hp)) {
        return 0;
    }
    str = slower(ejsToMulti(ejs, argv[0]));
    value = httpGetHeader(hp->conn, str);
    if (value) {
        result = ejsCreateStringFromAsc(ejs, value);
    } else {
        result = ESV(null);
    }
    return result;
}
示例#7
0
/*
    Connection callback
 */
static void webSocketNotify(HttpConn *conn, int event, int arg)
{
    Ejs             *ejs;
    EjsWebSocket    *ws;
    EjsByteArray    *ba;
    EjsAny          *data;
    HttpPacket      *packet;
    MprBuf          *content;
    ssize           len;

    if ((ws = httpGetConnContext(conn)) == 0) {
        return;
    }
    ejs = ws->ejs;
    if (!ejs->service) {
        /* Shutting down */
        return;
    }
    switch (event) {
    case HTTP_EVENT_STATE:
        if (arg == HTTP_STATE_CONTENT) {
            ws->protocol = (char*) httpGetHeader(conn, "Sec-WebSocket-Protocol");
            mprTrace(3, "Web socket protocol %s", ws->protocol);
            onWebSocketEvent(ws, HTTP_EVENT_APP_OPEN, 0, 0);
        }
        break;
    
    case HTTP_EVENT_READABLE:
        packet = httpGetPacket(conn->readq);
        content = packet->content;
        if (packet->type == WS_MSG_TEXT) {
            data = ejsCreateStringFromBytes(ejs, mprGetBufStart(content), mprGetBufLength(content));
        } else {
            len = httpGetPacketLength(packet);
            assert(len > 0);
            if ((ba = ejsCreateByteArray(ejs, len)) == 0) {
                return;
            }
            memcpy(ba->value, mprGetBufStart(content), len);
            ejsSetByteArrayPositions(ejs, ba, -1, len);
            data = ba;
        }
        onWebSocketEvent(ws, event, data, packet);
        break;

    case HTTP_EVENT_ERROR:
        if (!ws->error && !ws->closed) {
            ws->error = 1;
            onWebSocketEvent(ws, event, 0, 0);
            ws->closed = 1;
            onWebSocketEvent(ws, HTTP_EVENT_APP_CLOSE, 0, 0);
        }
        break;

    case HTTP_EVENT_APP_CLOSE:
        if (!ws->closed) {
            ws->closed = 1;
            onWebSocketEvent(ws, event, 0, 0);
        }
        break;
    }
}
示例#8
0
cchar *espGetHeader(HttpConn *conn, cchar *key)
{
    return httpGetHeader(conn, key);
}
示例#9
0
/*
    Run the request. This is invoked when all the input data has been received and buffered.
    This routine completely services the request.
 */
static void readyPhp(HttpQueue *q)
{
    HttpConn            *conn;
    HttpRx              *rx;
    HttpTx              *tx;
    MaPhp               *php;
    FILE                *fp;
    cchar               *value;
    char                shebang[MPR_MAX_STRING];
    zend_file_handle    file_handle;

    TSRMLS_FETCH();

    conn = q->conn;
    rx = conn->rx;
    tx = conn->tx;
    if ((php = q->queueData) == 0) {
        return;
    }
    /*
        Set the request context
     */
    zend_first_try {
        php->var_array = 0;
        SG(server_context) = conn;
        if (conn->username) {
            SG(request_info).auth_user = estrdup(conn->username);
        }
        if (conn->password) {
            SG(request_info).auth_password = estrdup(conn->password);
        }
        if ((value = httpGetHeader(conn, "Authorization")) != 0) {
            SG(request_info).auth_digest = estrdup(value);
        }
        SG(request_info).content_type = rx->mimeType;
        SG(request_info).path_translated = tx->filename;
        SG(request_info).content_length = (long) (ssize) rx->length;
        SG(sapi_headers).http_response_code = HTTP_CODE_OK;
        SG(request_info).query_string = rx->parsedUri->query;
        SG(request_info).request_method = rx->method;
        SG(request_info).request_uri = rx->uri;

        /*
            Workaround on MAC OS X where the SIGPROF is given to the wrong thread
         */
        PG(max_input_time) = -1;
        EG(timeout_seconds) = 0;

        /* The readBodyData callback may be invoked during startup */
        php_request_startup(TSRMLS_C);
        CG(zend_lineno) = 0;

    } zend_catch {
        mprError("Cannot start PHP request");
        zend_try {
            php_request_shutdown(0);
        } zend_end_try();
        httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "PHP initialization failed");
        return;
    } zend_end_try();

    /*
        Execute the script file
     */
    file_handle.filename = tx->filename;
    file_handle.free_filename = 0;
    file_handle.opened_path = 0;

#if LOAD_FROM_FILE
    file_handle.type = ZEND_HANDLE_FILENAME;
#else
    file_handle.type = ZEND_HANDLE_FP;
    if ((fp = fopen(tx->filename, "r")) == NULL) {
        if (rx->referrer) {
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s from %s", tx->filename, rx->referrer);
        } else {
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s", tx->filename);
        }
        return;
    }
    /*
        Check for shebang and skip
     */
    file_handle.handle.fp = fp;
    shebang[0] = '\0';
    if (fgets(shebang, sizeof(shebang), file_handle.handle.fp)) {}
    if (shebang[0] != '#' || shebang[1] != '!') {
        fseek(fp, 0L, SEEK_SET);
    }
#endif
    zend_try {
        php_execute_script(&file_handle TSRMLS_CC);
        if (!SG(headers_sent)) {
            sapi_send_headers(TSRMLS_C);
        }
    } zend_catch {
        php_request_shutdown(NULL);
        httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR,  "PHP script execution failed");
        return;
    } zend_end_try();

    zend_try {
        php_request_shutdown(NULL);
        SG(server_context) = NULL;
    } zend_catch {
        httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR,  "PHP script shutdown failed");
    } zend_end_try();

    httpFinalize(conn);
}