Example #1
0
static void cmd_settings(struct http_channel *c)
{
    struct http_response *rs = c->response;
    struct http_request *rq = c->request;
    struct http_session *s = locate_session(c);
    const char *content_type = http_lookup_header(rq->headers, "Content-Type");

    if (!s)
        return;

    if (rq->content_len && content_type &&
            !yaz_strcmp_del("text/xml", content_type, "; "))
    {
        xmlDoc *doc = xmlParseMemory(rq->content_buf, rq->content_len);
        xmlNode *root_n;
        int ret;
        if (!doc)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            release_session(c,s);
            return;
        }
        root_n = xmlDocGetRootElement(doc);
        ret = settings_read_node_x(root_n, s->psession, apply_local_setting);
        xmlFreeDoc(doc);
        if (ret)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            release_session(c,s);
            return;
        }
    }
    if (process_settings(s->psession, rq, rs) < 0)
    {
        release_session(c, s);
        return;
    }
    response_open(c, "settings");
    response_close(c, "settings");
    release_session(c, s);
}
Example #2
0
static int http_proxy(struct http_request *rq)
{
    struct http_channel *c = rq->channel;
    struct http_proxy *p = c->proxy;
    struct http_header *hp;
    struct http_buf *requestbuf;
    char server_port[16] = "";
    struct conf_server *ser = c->server;

    if (!p) // This is a new connection. Create a proxy channel
    {
        int sock;
        struct protoent *pe;
        int one = 1;

        if (!(pe = getprotobyname("tcp"))) {
            abort();
        }
        if ((sock = socket(PF_INET, SOCK_STREAM, pe->p_proto)) < 0)
        {
            yaz_log(YLOG_WARN|YLOG_ERRNO, "socket");
            return -1;
        }
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)
                        &one, sizeof(one)) < 0)
            abort();
        enable_nonblock(sock);
        if (connect(sock, (struct sockaddr *)
                    c->server->http_server->proxy_addr, 
                    sizeof(*c->server->http_server->proxy_addr)) < 0)
        {
            if (!is_inprogress()) 
            {
                yaz_log(YLOG_WARN|YLOG_ERRNO, "Proxy connect");
                return -1;
            }
        }
        p = xmalloc(sizeof(struct http_proxy));
        p->oqueue = 0;
        p->channel = c;
        p->first_response = 1;
        c->proxy = p;
        // We will add EVENT_OUTPUT below
        p->iochan = iochan_create(sock, proxy_io, EVENT_INPUT, "http_proxy");
        iochan_setdata(p->iochan, p);

        iochan_add(ser->iochan_man, p->iochan);
    }

    // Do _not_ modify Host: header, just checking it's existence

    if (!http_lookup_header(rq->headers, "Host"))
    {
        yaz_log(YLOG_WARN, "Failed to find Host header in proxy");
        return -1;
    }
    
    // Add new header about paraz2 version, host, remote client address, etc.
    {
        char server_via[128];

        hp = rq->headers;
        hp = http_header_append(c, hp, 
                                "X-Pazpar2-Version", PACKAGE_VERSION);
        hp = http_header_append(c, hp, 
                                "X-Pazpar2-Server-Host", ser->host);
        sprintf(server_port, "%d",  ser->port);
        hp = http_header_append(c, hp, 
                                "X-Pazpar2-Server-Port", server_port);
        yaz_snprintf(server_via, sizeof(server_via), 
                     "1.1 %s:%s (%s/%s)",  
                     ser->host ? ser->host : "@",
                     server_port, PACKAGE_NAME, PACKAGE_VERSION);
        hp = http_header_append(c, hp, "Via" , server_via);
        hp = http_header_append(c, hp, "X-Forwarded-For", c->addr);
    }
    
    requestbuf = http_serialize_request(rq);

    http_buf_enqueue(&p->oqueue, requestbuf);
    iochan_setflag(p->iochan, EVENT_OUTPUT);
    return 0;
}
Example #3
0
struct http_request *http_parse_request(struct http_channel *c,
                                        struct http_buf **queue,
                                        int len)
{
    struct http_request *r = nmem_malloc(c->nmem, sizeof(*r));
    char *p, *p2;
    char *start = nmem_malloc(c->nmem, len+1);
    char *buf = start;

    if (http_buf_read(c->http_server, queue, buf, len) < len)
    {
        yaz_log(YLOG_WARN, "http_buf_read < len (%d)", len);
        return 0;
    }
    r->search = "";
    r->channel = c;
    r->arguments = 0;
    r->headers = 0;
    r->content_buf = 0;
    r->content_len = 0;
    // Parse first line
    for (p = buf, p2 = r->method; *p && *p != ' ' && p - buf < 19; p++)
        *(p2++) = *p;
    if (*p != ' ')
    {
        yaz_log(YLOG_WARN, "Unexpected HTTP method in request");
        return 0;
    }
    *p2 = '\0';

    if (!(buf = strchr(buf, ' ')))
    {
        yaz_log(YLOG_WARN, "Missing Request-URI in HTTP request");
        return 0;
    }
    buf++;
    if (!(p = strchr(buf, ' ')))
    {
        yaz_log(YLOG_WARN, "HTTP Request-URI not terminated (too long?)");
        return 0;
    }
    *(p++) = '\0';
    if ((p2 = strchr(buf, '?'))) // Do we have arguments?
        *(p2++) = '\0';
    r->path = nmem_strdup(c->nmem, buf);
    if (p2)
    {
        r->search = nmem_strdup(c->nmem, p2);
        // Parse Arguments
        http_parse_arguments(r, c->nmem, p2);
    }
    buf = p;

    if (strncmp(buf, "HTTP/", 5))
        strcpy(r->http_version, "1.0");
    else
    {
        size_t skipped;
        buf += 5; // strlen("HTTP/")

        p = (char*) next_crlf(buf, &skipped);
        if (!p || skipped < 3 || skipped > 5)
            return 0;

        memcpy(r->http_version, buf, skipped);
        r->http_version[skipped] = '\0';
        buf = p;
    }
    strcpy(c->version, r->http_version);

    r->headers = 0;
    while (*buf)
    {
        size_t skipped;

        p = (char *) next_crlf(buf, &skipped);
        if (!p)
        {
            return 0;
        }
        else if (skipped == 0)
        {
            buf = p;
            break;
        }
        else
        {
            char *cp;
            char *n_v = nmem_malloc(c->nmem, skipped+1);
            struct http_header *h = nmem_malloc(c->nmem, sizeof(*h));

            memcpy(n_v, buf, skipped);
            n_v[skipped] = '\0';

            if (!(cp = strchr(n_v, ':')))
                return 0;
            h->name = nmem_strdupn(c->nmem, n_v, cp - n_v);
            cp++;
            while (isspace(*cp))
                cp++;
            h->value = nmem_strdup(c->nmem, cp);
            h->next = r->headers;
            r->headers = h;
            buf = p;
        }
    }

    // determine if we do keep alive
    if (!strcmp(c->version, "1.0"))
    {
        const char *v = http_lookup_header(r->headers, "Connection");
        if (v && !strcmp(v, "Keep-Alive"))
            c->keep_alive = 1;
        else
            c->keep_alive = 0;
    }
    else
    {
        const char *v = http_lookup_header(r->headers, "Connection");
        if (v && !strcmp(v, "close"))
            c->keep_alive = 0;
        else
            c->keep_alive = 1;
    }
    if (buf < start + len)
    {
        const char *content_type = http_lookup_header(r->headers,
                                                      "Content-Type");
        r->content_len = start + len - buf;
        r->content_buf = buf;

        if (!yaz_strcmp_del("application/x-www-form-urlencoded",
                            content_type, "; "))
        {
            http_parse_arguments(r, c->nmem, r->content_buf);
        }
    }
    return r;
}
Example #4
0
static void cmd_init(struct http_channel *c)
{
    struct http_request *r = c->request;
    const char *clear = http_argbyname(r, "clear");
    const char *content_type = http_lookup_header(r->headers, "Content-Type");
    unsigned int sesid;
    struct http_session *s;
    struct http_response *rs = c->response;
    struct conf_service *service = 0; /* no service (yet) */

    if (r->content_len && content_type &&
            !yaz_strcmp_del("text/xml", content_type, "; "))
    {
        xmlDoc *doc = xmlParseMemory(r->content_buf, r->content_len);
        xmlNode *root_n;
        if (!doc)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            return;
        }
        root_n = xmlDocGetRootElement(doc);
        service = service_create(c->server, root_n);
        xmlFreeDoc(doc);
        if (!service)
        {
            error(rs, PAZPAR2_MALFORMED_SETTING, 0);
            return;
        }
    }

    if (!service)
    {
        const char *service_name = http_argbyname(c->request, "service");
        service = locate_service(c->server, service_name);
        if (!service)
        {
            error(rs, PAZPAR2_NO_SERVICE, service_name ? service_name : "unnamed");
            return;
        }
    }
    sesid = make_sessionid();
    s = http_session_create(service, c->http_sessions, sesid);

    yaz_log(c->http_sessions->log_level, "Session init %u ", sesid);
    if (!clear || *clear == '0')
        session_init_databases(s->psession);
    else
        yaz_log(YLOG_LOG, "Session %u init: No databases preloaded", sesid);

    if (process_settings(s->psession, c->request, c->response) < 0)
        return;

    response_open(c, "init");
    wrbuf_printf(c->wrbuf, "<session>%d", sesid);
    if (c->server->server_id)
    {
        wrbuf_puts(c->wrbuf, ".");
        wrbuf_puts(c->wrbuf, c->server->server_id);
    }
    wrbuf_puts(c->wrbuf, "</session>"
               "<protocol>" PAZPAR2_PROTOCOL_VERSION "</protocol>");

    wrbuf_printf(c->wrbuf, "<keepAlive>%d</keepAlive>\n", 1000 * ((s->psession->service->session_timeout >= 20) ?
                 (s->psession->service->session_timeout - 10) : 50));
    response_close(c, "init");
}