1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 Index Data
3 * See the file LICENSE for details.
7 * \brief URL fetch utility
14 #include <yaz/comstack.h>
23 yaz_url_t yaz_url_create(void)
25 yaz_url_t p = xmalloc(sizeof(*p));
26 p->odr_in = odr_createmem(ODR_DECODE);
27 p->odr_out = odr_createmem(ODR_ENCODE);
32 void yaz_url_destroy(yaz_url_t p)
36 odr_destroy(p->odr_in);
37 odr_destroy(p->odr_out);
43 void yaz_url_set_proxy(yaz_url_t p, const char *proxy)
48 p->proxy = xstrdup(proxy);
51 static void extract_user_pass(NMEM nmem,
53 char **uri_lean, char **http_user,
56 const char *cp1 = strchr(uri, '/');
64 if (!strncmp(cp1, "://", 3))
67 const char *cp2 = cp1 + 3;
68 while (*cp2 && *cp2 != '/' && *cp2 != '@')
74 if (*cp2 == '@' && cp3)
76 *uri_lean = nmem_malloc(nmem, strlen(uri) + 1);
77 memcpy(*uri_lean, uri, cp1 + 3 - uri);
78 strcpy(*uri_lean + (cp1 + 3 - uri), cp2 + 1);
80 *http_user = nmem_strdupn(nmem, cp1 + 3, cp3 - (cp1 + 3));
81 *http_pass = nmem_strdupn(nmem, cp3 + 1, cp2 - (cp3 + 1));
86 *uri_lean = nmem_strdup(nmem, uri);
89 Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri,
91 Z_HTTP_Header *headers,
92 const char *buf, size_t len)
94 Z_HTTP_Response *res = 0;
95 int number_of_redirects = 0;
102 struct Z_HTTP_Header **last_header_entry;
103 const char *location = 0;
109 extract_user_pass(p->odr_out->mem, uri, &uri_lean,
110 &http_user, &http_pass);
112 gdu = z_get_HTTP_Request_uri(p->odr_out, uri_lean, 0, p->proxy ? 1 : 0);
113 gdu->u.HTTP_Request->method = odr_strdup(p->odr_out, method);
115 /* clear all headers - including "User-Agent", if already in headers
116 z_get_HTTP_Request_uri sets "User-Agent" header */
117 if (z_HTTP_header_lookup(headers, "User-Agent"))
118 gdu->u.HTTP_Request->headers = 0;
120 if (http_user && http_pass)
121 z_HTTP_header_add_basic_auth(p->odr_out,
122 &gdu->u.HTTP_Request->headers,
123 http_user, http_pass);
126 last_header_entry = &gdu->u.HTTP_Request->headers;
127 while (*last_header_entry)
128 last_header_entry = &(*last_header_entry)->next;
129 *last_header_entry = headers; /* attach user headers */
133 gdu->u.HTTP_Request->content_buf = (char *) buf;
134 gdu->u.HTTP_Request->content_len = len;
136 if (!z_GDU(p->odr_out, &gdu, 0, 0))
138 yaz_log(YLOG_WARN, "Can not encode HTTP request URL:%s", uri);
141 conn = cs_create_host_proxy(uri_lean, 1, &add, p->proxy);
144 yaz_log(YLOG_WARN, "Could not resolve URL: %s", uri);
146 else if (cs_connect(conn, add) < 0)
148 yaz_log(YLOG_WARN, "Can not connect to URL: %s", uri);
153 char *buf = odr_getbuf(p->odr_out, &len, 0);
155 if (cs_put(conn, buf, len) < 0)
156 yaz_log(YLOG_WARN, "cs_put failed URL: %s", uri);
161 int cs_res = cs_get(conn, &netbuffer, &netlen);
164 yaz_log(YLOG_WARN, "cs_get failed URL: %s", uri);
169 odr_setbuf(p->odr_in, netbuffer, cs_res, 0);
170 if (!z_GDU(p->odr_in, &gdu, 0, 0)
171 || gdu->which != Z_GDU_HTTP_Response)
173 yaz_log(YLOG_WARN, "HTTP decoding failed "
178 res = gdu->u.HTTP_Response;
189 location = z_HTTP_header_lookup(res->headers, "Location");
190 if (++number_of_redirects < 10 &&
191 location && (code == 301 || code == 302 || code == 307))
193 odr_reset(p->odr_out);
194 uri = odr_strdup(p->odr_out, location);
195 odr_reset(p->odr_in);
206 * c-file-style: "Stroustrup"
207 * indent-tabs-mode: nil
209 * vim: shiftwidth=4 tabstop=8 expandtab