1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
7 * \brief URL fetch utility
14 #include <yaz/comstack.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/cookie.h>
26 yaz_cookies_t cookies;
29 yaz_url_t yaz_url_create(void)
31 yaz_url_t p = xmalloc(sizeof(*p));
32 p->odr_in = odr_createmem(ODR_DECODE);
33 p->odr_out = odr_createmem(ODR_ENCODE);
35 p->max_redirects = 10;
36 p->w_error = wrbuf_alloc();
38 p->cookies = yaz_cookies_create();
42 void yaz_url_destroy(yaz_url_t p)
46 odr_destroy(p->odr_in);
47 odr_destroy(p->odr_out);
49 wrbuf_destroy(p->w_error);
50 yaz_cookies_destroy(p->cookies);
55 void yaz_url_set_proxy(yaz_url_t p, const char *proxy)
60 p->proxy = xstrdup(proxy);
63 void yaz_url_set_max_redirects(yaz_url_t p, int num)
65 p->max_redirects = num;
68 void yaz_url_set_verbose(yaz_url_t p, int num)
73 static void extract_user_pass(NMEM nmem,
75 char **uri_lean, char **http_user,
78 const char *cp1 = strchr(uri, '/');
86 if (!strncmp(cp1, "://", 3))
89 const char *cp2 = cp1 + 3;
90 while (*cp2 && *cp2 != '/' && *cp2 != '@')
96 if (*cp2 == '@' && cp3)
98 *uri_lean = nmem_malloc(nmem, strlen(uri) + 1);
99 memcpy(*uri_lean, uri, cp1 + 3 - uri);
100 strcpy(*uri_lean + (cp1 + 3 - uri), cp2 + 1);
102 *http_user = nmem_strdupn(nmem, cp1 + 3, cp3 - (cp1 + 3));
103 *http_pass = nmem_strdupn(nmem, cp3 + 1, cp2 - (cp3 + 1));
108 *uri_lean = nmem_strdup(nmem, uri);
111 const char *yaz_url_get_error(yaz_url_t p)
113 return wrbuf_cstr(p->w_error);
116 static void log_warn(yaz_url_t p)
118 yaz_log(YLOG_WARN, "yaz_url: %s", wrbuf_cstr(p->w_error));
121 Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri,
123 Z_HTTP_Header *user_headers,
124 const char *buf, size_t len)
126 Z_HTTP_Response *res = 0;
127 int number_of_redirects = 0;
129 yaz_cookies_reset(p->cookies);
130 wrbuf_rewind(p->w_error);
136 const char *location = 0;
142 extract_user_pass(p->odr_out->mem, uri, &uri_lean,
143 &http_user, &http_pass);
144 conn = cs_create_host2(uri_lean, 1, &add, p->proxy, &proxy_mode);
147 wrbuf_printf(p->w_error, "Can not resolve URL %s", uri);
153 z_get_HTTP_Request_uri(p->odr_out, uri_lean, 0, proxy_mode);
154 gdu->u.HTTP_Request->method = odr_strdup(p->odr_out, method);
155 yaz_cookies_request(p->cookies, p->odr_out, gdu->u.HTTP_Request);
156 for ( ; user_headers; user_headers = user_headers->next)
158 /* prefer new Host over user-supplied Host */
159 if (!strcmp(user_headers->name, "Host"))
161 /* prefer user-supplied User-Agent over YAZ' own */
162 else if (!strcmp(user_headers->name, "User-Agent"))
163 z_HTTP_header_set(p->odr_out, &gdu->u.HTTP_Request->headers,
164 user_headers->name, user_headers->value);
166 z_HTTP_header_add(p->odr_out, &gdu->u.HTTP_Request->headers,
167 user_headers->name, user_headers->value);
169 if (http_user && http_pass)
170 z_HTTP_header_add_basic_auth(p->odr_out,
171 &gdu->u.HTTP_Request->headers,
172 http_user, http_pass);
176 gdu->u.HTTP_Request->content_buf = (char *) buf;
177 gdu->u.HTTP_Request->content_len = len;
179 if (!z_GDU(p->odr_out, &gdu, 0, 0))
181 wrbuf_printf(p->w_error, "Can not encode HTTP request for URL %s",
186 if (cs_connect(conn, add) < 0)
188 wrbuf_printf(p->w_error, "Can not connect to URL %s", uri);
194 char *buf = odr_getbuf(p->odr_out, &len, 0);
196 fwrite(buf, 1, len, stdout);
197 if (cs_put(conn, buf, len) < 0)
199 wrbuf_printf(p->w_error, "cs_put fail for URL %s", uri);
206 int cs_res = cs_get(conn, &netbuffer, &netlen);
209 wrbuf_printf(p->w_error, "cs_get failed for URL %s", uri);
216 fwrite(netbuffer, 1, cs_res, stdout);
217 odr_setbuf(p->odr_in, netbuffer, cs_res, 0);
218 if (!z_GDU(p->odr_in, &gdu, 0, 0)
219 || gdu->which != Z_GDU_HTTP_Response)
221 wrbuf_printf(p->w_error, "HTTP decoding fail for "
227 res = gdu->u.HTTP_Response;
238 location = z_HTTP_header_lookup(res->headers, "Location");
239 if (++number_of_redirects <= p->max_redirects &&
240 location && (code == 301 || code == 302 || code == 307))
243 const char *nlocation = yaz_check_location(p->odr_in, uri,
244 location, &host_change);
246 odr_reset(p->odr_out);
247 uri = odr_strdup(p->odr_out, nlocation);
251 yaz_cookies_response(p->cookies, res);
252 odr_reset(p->odr_in);
260 * c-file-style: "Stroustrup"
261 * indent-tabs-mode: nil
263 * vim: shiftwidth=4 tabstop=8 expandtab