⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http-client.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@file http-client.c  Simple HTTP tool. * * @author Pekka Pessi <Pekka.Pessi@nokia.com>. * * @date Created: Fri Mar 30 12:05:21 2001 ppessi */#include "config.h"/**@page http_client Make HTTP request *  * @par Name牋牋 * http-client - HTTP request tool * * @par Synopsis * * <tt>http-client [OPTIONS] url</tt> * * @par Description *  * The @em http-client utility sends a HTTP request to an HTTP server or proxy. * * @par  * * The @em http-client tool will print out status line and interesting * headers from the response. The message body is also printed. * * @par Options * * The @e http-client utility accepts following command line options: * <dl> * <dt>--method=name</dt> * <dd>Specify the request method name (GET by default). * </dd> * <dt>--proxy=url</dt> * <dd>Specifies the proxy via which the request will be sent. * </dd> * <dt>--ua=value</dt> * <dd>Specifies the User-Agent header field. * </dd> * <dt>--mf=n</dt> * <dd>Specify the initial Max-Forwards count. * </dd> * <dt>--pipe</dt> * <dd>Use pipelining (do not shutdown client connection after request). * </dd> * <dt>--extra</dt> * <dd>Insert standard input to the requests. * </dd> * </dl> * * @par Examples * * You want to query supported features of http://connecting.nokia.com: * @code * $ http-client --method OPTIONS http://connecting.nokia.com * @endcode * * @par Environment * @c NTH_DEBUG, @c TPORT_DEBUG, @c TPORT_LOG. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * <hr> */#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>typedef struct context_s context_t;#define NTH_CLIENT_MAGIC_T context_t#include <sofia-sip/nth.h>#include <sofia-sip/http_header.h>#include <sofia-sip/http_tag.h>#include <sofia-sip/tport_tag.h>#include <sofia-sip/auth_client.h>struct context_s {  su_home_t   	  c_home[1];  su_root_t   	 *c_root;  nth_engine_t 	 *c_engine;  nth_client_t   *c_clnt;  char const     *c_user;  char const     *c_pass;  auth_client_t  *c_auth;  int             c_pre;  int             c_pending;};staticchar const name[] = "http-client";staticint header_print(FILE *stream, char const *fmt, http_header_t const *h){  char s[1024];  msg_header_field_e(s, sizeof(s), (msg_header_t*)h, 0);  s[sizeof(s) - 1] = '\0';  if (fmt && strcmp(fmt, "%s"))    return fprintf(stream, fmt, s);  if (fputs(s, stream) >= 0)    return strlen(s);  return -1;}staticint payload_print(FILE *stream, msg_payload_t const *pl){  for (; pl; pl = pl->pl_next) {    fprintf(stream, "%.*s", (int)pl->pl_len, pl->pl_data);  }  return 0;}static char *read_file(FILE *stream){  int n;  char *buf;  off_t used, size;  if (stream == NULL) {    errno = EINVAL;    return NULL;  }  /* Read block by block */  used = 0;  size = 512;  buf = malloc(size);  while (buf) {    n = fread(buf + used, 1, size - used - 1, stream);    used += n;    if (n < size - used - 1) {      if (feof(stream))	;      else if (ferror(stream))	free(buf), buf = NULL;      break;    }    buf = realloc(buf, 2 * size);  }  if (buf)    if (used < size)      buf[used] = '\0';  return buf;}char const _usage[] = "usage: %s [OPTIONS] url\n""       where OPTIONS are as follows\n""       --method=name\n""       --proxy=url\n""       --user=user:password\n""       --ua=value\n""       --mf=n\n""       --pipe\n""       --extra\n";staticvoid usage(int rc){  fprintf(stderr, _usage, name);  exit(rc);}static int response(context_t *context,			       nth_client_t *oreq,			       http_t const *http);int main(int argc, char *argv[]){  su_home_t *home;  context_t context[1] = {{{SU_HOME_INIT(context)}}};  http_method_t method;  char     *o_proxy = NULL,     *o_user = NULL,    *o_max_forwards = NULL,    *o_method_name = "GET",    *o_user_agent = "http-client/1.0 " "nth/" NTH_VERSION;  int     o_pipe = 0, o_extra = 0;     char *extra = NULL;  char *v;#define MATCH(s, o) \      ((strcmp(s, o) == 0))#define MATCH1(s, o) \      ((strncmp(s, o, strlen(o)) == 0) && \       (v = (s[strlen(o)] ? s + strlen(o) : argv++[1])))#define MATCH2(s, o) \      ((strncmp(s, o, strlen(o)) == 0) && \       (s[strlen(o)] == '=' || s[strlen(o)] == '\0') && \       (v = s[strlen(o)] ? s + strlen(o) + 1 : argv++[1]))  while ((v = argv++[1])) {    if (v[0] != '-')                 { argv--; break; }    else if (MATCH(v, "-"))          { break; }    else if (MATCH2(v, "--method"))  { o_method_name = v;  continue; }    else if (MATCH2(v, "--mf"))      { o_max_forwards = v; continue; }    else if (MATCH2(v, "--proxy"))   { o_proxy = v;        continue; }    else if (MATCH2(v, "--user"))    { o_user = v;         continue; }    else if (MATCH2(v, "--ua"))      { o_user_agent = v;   continue; }    else if (MATCH(v, "--pipe"))     { o_pipe = 1;         continue; }    else if (MATCH(v, "--extra"))    { o_extra = 1;        continue; }    else if (MATCH(v, "--help"))     { usage(0);           continue; }    else       usage(1);  }  if (!argv[1])    usage(1);  method = http_method_code(o_method_name);  if (o_user) {    char *pass = strchr(o_user, ':');    if (pass) *pass++ = '\0';    context->c_user = o_user, context->c_pass = pass;  }  su_init();  su_home_init(home = context->c_home);  if (o_extra) {    if (isatty(0))       fprintf(stderr, 	      "Type extra HTTP headers, empty line then HTTP message body "	      "(^D when complete):\n");    fflush(stderr);    extra = read_file(stdin);  }  context->c_root = su_root_create(context);  if (context->c_root) {    context->c_engine =       nth_engine_create(context->c_root, 			NTHTAG_ERROR_MSG(0),			TAG_END());    if (context->c_engine) {      while ((v = argv++[1])) {	nth_client_t *clnt;	clnt = nth_client_tcreate(context->c_engine,				  response, context, 				  method, o_method_name,				  URL_STRING_MAKE(v),				  NTHTAG_PROXY(o_proxy),				  HTTPTAG_USER_AGENT_STR(o_user_agent),				  HTTPTAG_MAX_FORWARDS_STR(o_max_forwards),				  TPTAG_REUSE(o_pipe),				  HTTPTAG_HEADER_STR(extra),				  TAG_END());	if (clnt)	  context->c_pending++;      }      if (context->c_pending)	su_root_run(context->c_root);       nth_engine_destroy(context->c_engine), context->c_engine = NULL;    }    su_root_destroy(context->c_root);  }  su_deinit();  return 0;}/** Handle responses to request */staticint response(context_t *c,	     nth_client_t *clnt,	     http_t const *http){  nth_client_t *newclnt = NULL;  int status;  if (http) {    status = http->http_status->st_status;  } else {    status = nth_client_status(clnt);    fprintf(stderr, "HTTP/1.1 %u Error\n", status);  }   if (http && (c->c_pre || status >= 200)) {    http_header_t *h = (http_header_t *)http->http_status;    char hname[64];    for (; h; h = (http_header_t *)h->sh_succ) {      if (h == (http_header_t *)http->http_payload)	continue;      else if (h == (http_header_t *)http->http_separator)	continue;      else if (!h->sh_class->hc_name)	header_print(stdout, NULL, h);      else if (h->sh_class->hc_name[0]) {	snprintf(hname, sizeof hname, "%s: %%s\n", h->sh_class->hc_name);	header_print(stdout, hname, h);       } else {	header_print(stdout, "%s\n", h);       }    }    printf("\n");    if (http->http_payload)      payload_print(stdout, http->http_payload);    fflush(stdout);  }  if (status < 200)    return 0;  if (status == 401 && http->http_www_authenticate) {    char const *user = c->c_user;    char const *pass = c->c_pass;    if (!user || !pass) {      url_t const *url = nth_client_url(clnt);      if (url) {	user = url->url_user, pass = url->url_password;       }    }    //if (user && pass &&    if (	auc_challenge(&c->c_auth, c->c_home, 		      http->http_www_authenticate,		      http_authorization_class) > 0) {      char const *scheme = NULL;      char const *realm = NULL;      scheme = http->http_www_authenticate->au_scheme;      realm = msg_params_find(http->http_www_authenticate->au_params,				"realm=");      if (auc_all_credentials(&c->c_auth, scheme, realm, user, pass)	  >= 0)	newclnt = nth_client_tcreate(c->c_engine, 				     NULL, NULL, HTTP_NO_METHOD, NULL,				     NTHTAG_AUTHENTICATION(&c->c_auth),				     NTHTAG_TEMPLATE(clnt),				     TAG_END());    }  }  if (status == 302 && http->http_location) {    url_t loc[1];        *loc = *http->http_location->loc_url;    newclnt = nth_client_tcreate(c->c_engine, NULL, NULL,				 HTTP_NO_METHOD, 				 (url_string_t *)loc,				 NTHTAG_TEMPLATE(clnt),				 TAG_END());  }  if (newclnt)    c->c_pending++;    nth_client_destroy(clnt);  if (c->c_pending-- == 1)    su_root_break(c->c_root);  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -