Пример #1
0
static int bad_request(struct strbuf *hdr, const struct service_cmd *c)
{
	const char *proto = getenv("SERVER_PROTOCOL");

	if (proto && !strcmp(proto, "HTTP/1.1")) {
		http_status(hdr, 405, "Method Not Allowed");
		hdr_str(hdr, "Allow",
			!strcmp(c->method, "GET") ? "GET, HEAD" : c->method);
	} else
		http_status(hdr, 400, "Bad Request");
	hdr_nocache(hdr);
	end_headers(hdr);
	return 0;
}
Пример #2
0
bool http_header::build_response(string& out) const
{
	out.clear();

	if (status_ > 0)
	{
		if (cgi_mode_)
			out.format("STATUS: %d\r\n", status_);
		else
		{
			out = "HTTP/1.1 ";
			out << status_ << " " << http_status(status_) << "\r\n";

			time_t now = time(NULL);
			char buf[64];
			date_format(buf, sizeof(buf), now);
			out << "Date: " << buf << "\r\n";
			out << "Server: acl\r\n";
		}
	}

	if (!cookies_.empty())
	{
		std::list<HttpCookie*>::const_iterator it = cookies_.begin();
		for (; it != cookies_.end(); ++it)
		{
			out.format_append("Set-Cookie: %s=%s",
				(*it)->getName(), (*it)->getValue());
			const std::list<HTTP_PARAM*>& params = (*it)->getParams();
			std::list<HTTP_PARAM*>::const_iterator cit = params.begin();
			for (; cit != params.end(); ++ cit)
			{
				out.format_append("; %s=%s",
					(*cit)->name, (*cit)->value);
			}
			out << "\r\n";
		}
	}

	// 添加分段响应字段
	if (range_from_ >= 0 && range_to_ >= range_from_ && range_total_ > 0)
		out << "Content-Range: bytes=" << range_from_ << '-'
			<< range_to_ << '/' << range_total_ << "\r\n";

	// 如果是 gzip 压缩数据,当非 chunked 传输时,必须取消 Content-Length 字段,
	// 同时禁止保持长连接,即: Connection: close
	if (transfer_gzip_)
	{
		out << "Content-Encoding: gzip\r\n";

		if (!chunked_transfer_ && keep_alive_)
			const_cast<http_header*>(this)->keep_alive_ = false;
		if (content_length_ > 0)
			const_cast<http_header*>(this)->content_length_ = -1;
	}

	build_common(out);
	out << "\r\n";
	return true;
}
Пример #3
0
static NORETURN void die_webcgi(const char *err, va_list params)
{
	if (dead <= 1) {
		vreportf("fatal: ", err, params);

		http_status(500, "Internal Server Error");
		hdr_nocache();
		end_headers();
	}
	exit(0); /* we successfully reported a failure ;-) */
}
Пример #4
0
bool
connection_base::print_error(std::streambuf &buf, http_error const &http) const {

	std::ostream stream(&buf);
	stream << http_status(http.code());
	stream << http_date(boost::posix_time::second_clock::universal_time());
	stream << http_header::server();
	stream << http_header::connection_close();
	stream << http_header("Content-Type", "text/plain; charset=utf-8");
	stream << http_constants<char>::endl;
	return true;
}
Пример #5
0
static NORETURN void not_found(const char *err, ...)
{
	va_list params;

	http_status(404, "Not Found");
	hdr_nocache();
	end_headers();

	va_start(params, err);
	if (err && *err)
		vfprintf(stderr, err, params);
	va_end(params);
	exit(0);
}
Пример #6
0
static NORETURN void forbidden(const char *err, ...)
{
	va_list params;

	http_status(403, "Forbidden");
	hdr_nocache();
	end_headers();

	va_start(params, err);
	if (err && *err)
		vfprintf(stderr, err, params);
	va_end(params);
	exit(0);
}
Пример #7
0
static JSBool
req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
{
    int status = http_status(cx, obj);
    if(status < 0)
        return JS_FALSE;

    if(INT_FITS_IN_JSVAL(status)) {
        JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
        return JS_TRUE;
    } else {
        JS_ReportError(cx, "Invalid HTTP status.");
        return JS_FALSE;
    }
}
Пример #8
0
/** Process an incoming action request
	@returns non-zero on success, 0 on failure (errno set)
 **/
int http_action_request(HTTP *http,char *action)
{
	if (gui_post_action(action)==-1)
	{
		http_status(http,HTTP_ACCEPTED);
		http_type(http,"text/plain");
		http_format(http,"Goodbye");
		http_send(http);
		http_close(http);
		shutdown_now();
		return 1;
	}
	else
		return 0;
}
Пример #9
0
static void parse_response( void )
{
    char res[] =
        "HTTP/1.1 200 OK\r\n"
        "Server: GitHub.com\r\n"
        "Date: Sat, 27 Jun 2015 04:10:06 GMT\r\n"
        "Content-Type: text/html; charset=utf-8\r\n"
        "Transfer-Encoding: chunked\r\n"
        "Status: 200 OK\r\n"
        "Content-Security-Policy: default-src *; script-src assets-cdn.github.com collector-cdn.github.com; object-src assets-cdn.github.com; style-src 'self' 'unsafe-inline' 'unsafe-eval' assets-cdn.github.com; img-src 'self' data: assets-cdn.github.com identicons.github.com www.google-analytics.com collector.githubapp.com *.githubusercontent.com *.gravatar.com *.wp.com; media-src 'none'; frame-src 'self' render.githubusercontent.com gist.github.com www.youtube.com player.vimeo.com checkout.paypal.com; font-src assets-cdn.github.com; connect-src 'self' live.github.com wss://live.github.com uploads.github.com status.github.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com\r\n"
        "Cache-Control: no-cache\r\n"
        "Vary: X-PJAX\r\n"
        "X-UA-Compatible: IE=Edge,chrome=1\r\n"
        "Set-Cookie: logged_in=no; domain=.github.com; path=/; expires=Wed, 27 Jun 2035 04:10:06 -0000; secure; HttpOnly\r\n"
        "X-Request-Id: 8ea8d359ded1d2d30094d38b2a4e73d3\r\n"
        "X-Runtime: 0.037659\r\n"
        "X-GitHub-Request-Id: 999DDDE5:0A3A:102882A:558E221D\r\n"
        "Strict-Transport-Security: max-age=31536000; includeSubdomains; preload\r\n"
        "X-Content-Type-Options: nosniff\r\n"
        "X-XSS-Protection: 1; mode=block\r\n"
        "X-Frame-Options: deny\r\n"
        "Vary: Accept-Encoding\r\n"
        "X-Served-By: 1868c9f28a71d80b2987f48dbd1824a0\r\n"
        "\r\n";
    size_t len = sizeof( res );
    uint64_t i = 0;
    int rc = 0;
    float start = 0, end = 0, elapsed = 0;
    uint16_t maxhdrlen = UINT16_MAX;
    http_t *r = http_alloc(20);
    
    start = (float)clock()/CLOCKS_PER_SEC;
    for( i = 0; i < NLOOP; i++ ){
        rc = http_res_parse( r, res, len, maxhdrlen );
        assert( rc == HTTP_SUCCESS );
        assert( http_version(r) == HTTP_V11 );
        assert( http_status(r) == HTTP_OK );
        assert( r->nheader == 19 );
        http_init( r );
    }
    end = (float)clock()/CLOCKS_PER_SEC;
    elapsed = end - start;
    
    http_free( r );
    
    printf("\tElapsed %f seconds.\n", elapsed );
    printf("\t%0.9f -> %f req/sec.\n", elapsed / NLOOP, 1.00000 / ( elapsed / NLOOP ) );
}
Пример #10
0
static NORETURN void die_webcgi(const char *err, va_list params)
{
	static int dead;

	if (!dead) {
		char buffer[1000];
		dead = 1;

		vsnprintf(buffer, sizeof(buffer), err, params);
		fprintf(stderr, "fatal: %s\n", buffer);
		http_status(500, "Internal Server Error");
		hdr_nocache();
		end_headers();
	}
	exit(0); /* we successfully reported a failure ;-) */
}
Пример #11
0
Файл: http.c Проект: snip/aprsc
static void http_router(struct evhttp_request *r, void *which_server)
{
	char *remote_host;
	ev_uint16_t remote_port;
	const char *uri = evhttp_request_get_uri(r);
	struct evhttp_connection *conn = evhttp_request_get_connection(r);
	evhttp_connection_get_peer(conn, &remote_host, &remote_port);
	
	hlog(LOG_DEBUG, "http %s [%s] request %s", (which_server == (void *)1) ? "status" : "upload", remote_host, uri);
	
	http_requests++;
	
	/* status server routing */
	if (which_server == (void *)1) {
		if (strncmp(uri, "/status.json", 12) == 0) {
			http_status(r);
			return;
		}
		
		if (strncmp(uri, "/counterdata?", 13) == 0) {
			http_counterdata(r, uri);
			return;
		}
		
		http_route_static(r, uri);
		return;
	}
	
	/* position upload server routing */
	if (which_server == (void *)2) {
		if (strncmp(uri, "/", 7) == 0) {
			http_upload_position(r, remote_host);
			return;
		}
		
		hlog(LOG_DEBUG, "http request on upload server for '%s': 404 not found", uri);
		evhttp_send_error(r, HTTP_NOTFOUND, "Not found");
		return;
	}
	
	hlog(LOG_ERR, "http request on unknown server for '%s': 404 not found", uri);
	evhttp_send_error(r, HTTP_NOTFOUND, "Server not found");
	
	return;
}
Пример #12
0
static void check_content_type(const char *accepted_type)
{
	const char *actual_type = getenv("CONTENT_TYPE");

	if (!actual_type)
		actual_type = "";

	if (strcmp(actual_type, accepted_type)) {
		http_status(415, "Unsupported Media Type");
		hdr_nocache();
		end_headers();
		format_write(1,
			"Expected POST with Content-Type '%s',"
			" but received '%s' instead.\n",
			accepted_type, actual_type);
		exit(0);
	}
}
Пример #13
0
bool
connection_base::print_static_content(
	std::string const &content_type, std::string const &content, std::streambuf &buf) const {

	if (!ws_info_.empty()) {
		return false;
	}

	std::ostream stream(&buf);

	stream << http_status(200);
	stream << http_header::connection_close();
	print_common_headers(content_type, buf);
	stream << "Content-Length: " << content.size() << http_constants<char>::endl;
	stream << http_constants<char>::endl;
	stream << content;
	return true;
}
Пример #14
0
bool http_header::build_response(string& out) const
{
	out.clear();

	if (status_ > 0)
	{
		if (cgi_mode_)
			out.format("STATUS: %d\r\n", status_);
		else
		{
			out = "HTTP/1.1 ";
			out << status_ << " " << http_status(status_) << "\r\n";

			time_t now = time(NULL);
			char buf[64];
			date_format(buf, sizeof(buf), now);
			out << "Date: " << buf << "\r\n";
		}
	}

	if (!cookies_.empty())
	{
		std::list<HttpCookie*>::const_iterator it = cookies_.begin();
		for (; it != cookies_.end(); ++it)
		{
			out.format_append("Set-Cookie: %s=%s",
				(*it)->getName(), (*it)->getValue());
			const std::list<HTTP_PARAM*>& params = (*it)->getParams();
			std::list<HTTP_PARAM*>::const_iterator cit = params.begin();
			for (; cit != params.end(); ++ cit)
			{
				out.format_append("; %s=%s",
					(*cit)->name, (*cit)->value);
			}
			out << "\r\n";
		}
	}

	build_common(out);
	out << "\r\n";
	return true;
}
Пример #15
0
static inline int parse_response( lua_State *L, lhttp_t *h, char *buf,
                                  size_t len )
{
    http_t *r = h->r;
    int rc = 0;

    luaL_checktype( L, 2, LUA_TTABLE );
    luaL_checktype( L, 3, LUA_TTABLE );
    rc = http_res_parse( r, buf, len, h->maxhdrlen );
    if( rc == HTTP_SUCCESS )
    {
        uint8_t i = 0;
        uint8_t nheader = r->nheader;
        uintptr_t key = 0;
        uint16_t klen = 0;
        uintptr_t val = 0;
        uint16_t vlen = 0;

        // export to table
        lua_settop( L, 3 );
        // add to header table
        for(; i < nheader; i++ ){
            http_getheader_at( r, &key, &klen, &val, &vlen, i );
            lstate_strll2tbl( L, buf + key, klen, buf + val, vlen );
        }
        lua_pop( L, 1 );
        lstate_num2tbl( L, "version", http_version( r ) );
        lstate_num2tbl( L, "status", http_status( r ) );
        lstate_strl2tbl( L, "reason", buf + r->msg, r->msglen );
        // initialize
        http_init( r );
    }

    // add status
    lua_pushinteger( L, rc );

    return 1;
}
Пример #16
0
bool
connection_base::print_headers(std::string const &content_type, std::streambuf &buf) const {

	bool is_websocket = !ws_info_.empty();
	if (is_websocket && !ws_info_.valid()) {
		return false;
	}

	std::ostream stream(&buf);
	if (is_websocket) {
		ws_info_.write_headers(stream);
	}
	else {
		stream << http_status(200);
		stream << http_header::connection_close();
		stream << http_header("Transfer-Encoding", "chunked");
	}
	print_common_headers(content_type, buf);
	stream << http_constants<char>::endl;
	if (is_websocket) {
		ws_info_.write_body(stream);
	}
	return true;
}
Пример #17
0
/** Process an incoming request
	@returns nothing
 **/
void http_response(SOCKET fd)
{
	HTTP *http = http_create(fd);
	size_t len;
	int content_length = 0;
	char *user_agent = NULL;
	char *host = NULL;
	int keep_alive = 0;
	char *connection = NULL;
	char *accept = NULL;
	struct s_map {
		char *name;
		enum {INTEGER,STRING} type;
		void *value;
		size_t sz;
	} map[] = {
		{"Content-Length", INTEGER, (void*)&content_length, 0},
		{"Host", STRING, (void*)&host, 0},
		{"Keep-Alive", INTEGER, (void*)&keep_alive, 0},
		{"Connection", STRING, (void*)&connection, 0},
		{"Accept", STRING, (void*)&accept, 0},
	};

	while ( (int)(len=recv_data(fd,http->query,sizeof(http->query)))>0 )
	{
		/* first term is always the request */
		char *request = http->query;
		char method[32];
		char uri[1024];
		char version[32];
		char *p = strchr(http->query,'\r');
		int v;
		
		/* initialize the response */
		http_reset(http);

		/* read the request string */
		if (sscanf(request,"%s %s %s",method,uri,version)!=3)
		{
			http_status(http,HTTP_BADREQUEST);
			http_format(http,HTTP_BADREQUEST);
			http_type(http,"text/html");
			http_send(http);
			break;
		}

		/* read the rest of the header */
		while (p!=NULL && (p=strchr(p,'\r'))!=NULL) 
		{
 			*p = '\0';
			p+=2;
			for ( v=0 ; v<sizeof(map)/sizeof(map[0]) ; v++ )
			{
				if (map[v].sz==0) map[v].sz = strlen(map[v].name);
				if (strnicmp(map[v].name,p,map[v].sz)==0 && strncmp(p+map[v].sz,": ",2)==0)
				{
					if (map[v].type==INTEGER) { *(int*)(map[v].value) = atoi(p+map[v].sz+2); break; }
					else if (map[v].type==STRING) { *(char**)map[v].value = p+map[v].sz+2; break; }
				}
			}
		}
		output_verbose("%s (host='%s', len=%d)",http->query,host?host:"???",content_length);

		/* reject anything but a GET */
		if (stricmp(method,"GET")!=0)
		{
			http_status(http,HTTP_METHODNOTALLOWED);
			http_format(http,HTTP_METHODNOTALLOWED);
			http_type(http,"text/html");
			/* technically, we should add an Allow entry to the response header */
			http_send(http);
			break;
		}

		/* handle request */
		if ( strcmp(uri,"/favicon.ico")==0 )
		{
			if ( http_favicon(http) )
				http_status(http,HTTP_OK);
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else {
			static struct s_map {
				char *path;
				int (*request)(HTTP*,char*);
				char *success;
				char *failure;
			} map[] = {
				/* this is the map of recognize request types */
				{"/xml/",		http_xml_request,		HTTP_OK, HTTP_NOTFOUND},
				{"/gui/",		http_gui_request,		HTTP_OK, HTTP_NOTFOUND},
				{"/output/",	http_output_request,	HTTP_OK, HTTP_NOTFOUND},
				{"/action/",	http_action_request,	HTTP_ACCEPTED,HTTP_NOTFOUND},
				{"/rt/",		http_get_rt,			HTTP_OK, HTTP_NOTFOUND},
				{"/perl/",		http_run_perl,			HTTP_OK, HTTP_NOTFOUND},
				{"/gnuplot/",	http_run_gnuplot,		HTTP_OK, HTTP_NOTFOUND},
				{"/java/",		http_run_java,			HTTP_OK, HTTP_NOTFOUND},
				{"/python/",	http_run_python,		HTTP_OK, HTTP_NOTFOUND},
				{"/r/",			http_run_r,				HTTP_OK, HTTP_NOTFOUND},
				{"/scilab/",	http_run_scilab,		HTTP_OK, HTTP_NOTFOUND},
				{"/octave/",	http_run_octave,		HTTP_OK, HTTP_NOTFOUND},
			};
			int n;
			for ( n=0 ; n<sizeof(map)/sizeof(map[0]) ; n++ )
			{
				size_t len = strlen(map[n].path);
				if (strncmp(uri,map[n].path,len)==0)
				{
					if ( map[n].request(http,uri+len) )
						http_status(http,map[n].success);
					else
						http_status(http,map[n].failure);
					http_send(http);
					goto Next;
				}
			}
		}
		/* deprecated XML usage */
		if (strncmp(uri,"/",1)==0 )
		{
			if ( http_xml_request(http,uri+1) )
			{	
				output_warning("deprecate XML usage in request '%s'", uri);
				http_status(http,HTTP_OK);
			}
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else 
		{
			http_status(http,HTTP_NOTFOUND);
			http_format(http,HTTP_NOTFOUND);
			http_type(http,"text/html");
			http_send(http);
		}

		/* keep-alive not desired*/
Next:
		if (connection && stricmp(connection,"close")==0)
			break;
	}
	http_close(http);
	output_verbose("socket %d closed",http->s);
}
Пример #18
0
int main(int argc, char **argv)
{
	char *method = getenv("REQUEST_METHOD");
	char *dir;
	struct service_cmd *cmd = NULL;
	char *cmd_arg = NULL;
	int i;

	git_setup_gettext();

	git_extract_argv0_path(argv[0]);
	set_die_routine(die_webcgi);

	if (!method)
		die("No REQUEST_METHOD from server");
	if (!strcmp(method, "HEAD"))
		method = "GET";
	dir = getdir();

	for (i = 0; i < ARRAY_SIZE(services); i++) {
		struct service_cmd *c = &services[i];
		regex_t re;
		regmatch_t out[1];

		if (regcomp(&re, c->pattern, REG_EXTENDED))
			die("Bogus regex in service table: %s", c->pattern);
		if (!regexec(&re, dir, 1, out, 0)) {
			size_t n;

			if (strcmp(method, c->method)) {
				const char *proto = getenv("SERVER_PROTOCOL");
				if (proto && !strcmp(proto, "HTTP/1.1")) {
					http_status(405, "Method Not Allowed");
					hdr_str("Allow", !strcmp(c->method, "GET") ?
						"GET, HEAD" : c->method);
				} else
					http_status(400, "Bad Request");
				hdr_nocache();
				end_headers();
				return 0;
			}

			cmd = c;
			n = out[0].rm_eo - out[0].rm_so;
			cmd_arg = xmemdupz(dir + out[0].rm_so + 1, n - 1);
			dir[out[0].rm_so] = 0;
			break;
		}
		regfree(&re);
	}

	if (!cmd)
		not_found("Request not supported: '%s'", dir);

	setup_path();
	if (!enter_repo(dir, 0))
		not_found("Not a git repository: '%s'", dir);
	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
	    access("git-daemon-export-ok", F_OK) )
		not_found("Repository not exported: '%s'", dir);

	git_config(http_config, NULL);
	cmd->imp(cmd_arg);
	return 0;
}
Пример #19
0
void http_response(SOCKET fd)
{
	HTTP *http = http_create(fd);
	size_t len;
	int content_length = 0;
	char *user_agent = NULL;
	char *host = NULL;
	int keep_alive = 0;
	char *connection = NULL;
	char *accept = NULL;
	struct s_map {
		char *name;
		enum {INTEGER,STRING} type;
		void *value;
		int sz;
	} map[] = {
		{"Content-Length", INTEGER, (void*)&content_length, 0},
		{"Host", STRING, (void*)&host, 0},
		{"Keep-Alive", INTEGER, (void*)&keep_alive, 0},
		{"Connection", STRING, (void*)&connection, 0},
		{"Accept", STRING, (void*)&accept, 0},
	};

	while ( (int)(len=recv_data(fd,http->query,sizeof(http->query)))>0 )
	{
		/* first term is always the request */
		char *request = http->query;
		char method[32];
		char uri[1024];
		char version[32];
		char *p = strchr(http->query,'\r');
		int v;

		/* read the request string */
		if (sscanf(request,"%s %s %s",method,uri,version)!=3)
		{
			http_status(http,HTTP_BADREQUEST);
			http_format(http,HTTP_BADREQUEST);
			http_type(http,"text/html");
			http_send(http);
			break;
		}

		/* read the rest of the header */
		while (p!=NULL && (p=strchr(p,'\r'))!=NULL) 
		{
 			*p = '\0';
			p+=2;
			for ( v=0 ; v<sizeof(map)/sizeof(map[0]) ; v++ )
			{
				if (map[v].sz==0) map[v].sz = strlen(map[v].name);
				if (strnicmp(map[v].name,p,map[v].sz)==0 && strncmp(p+map[v].sz,": ",2)==0)
				{
					if (map[v].type==INTEGER) { *(int*)(map[v].value) = atoi(p+map[v].sz+2); break; }
					else if (map[v].type==STRING) { *(char**)map[v].value = p+map[v].sz+2; break; }
				}
			}
		}
		output_verbose("%s (host='%s', len=%d)",http->query,host?host:"???",content_length);

		/* reject anything but a GET */
		if (stricmp(method,"GET")!=0)
		{
			http_status(http,HTTP_METHODNOTALLOWED);
			http_format(http,HTTP_METHODNOTALLOWED);
			http_type(http,"text/html");
			/* technically, we should add an Allow entry to the response header */
			http_send(http);
			break;
		}

		/* handle request */
		if (strncmp(uri,"/gui/",5)==0 )
		{
			if ( http_gui_request(http,uri+5) )
				http_status(http,HTTP_OK);
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else if (strncmp(uri,"/output/",8)==0 )
		{
			if ( http_output_request(http,uri+8) )
				http_status(http,HTTP_OK);
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else if (strncmp(uri,"/action/",8)==0) 
		{
			if ( http_action_request(http,uri+8) )
				http_status(http,HTTP_ACCEPTED);
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else if ( strcmp(uri,"/favicon.ico")==0 )
		{
			if ( http_favicon(http) )
				http_status(http,HTTP_OK);
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else if (strncmp(uri,"/",1)==0 )
		{
			if ( http_xml_request(http,uri+1) )
				http_status(http,HTTP_OK);
			else
				http_status(http,HTTP_NOTFOUND);
			http_send(http);
		}
		else 
		{
			http_status(http,HTTP_NOTFOUND);
			http_format(http,HTTP_NOTFOUND);
			http_type(http,"text/html");
			http_send(http);
		}

		/* keep-alive not desired*/
		if (connection && stricmp(connection,"close")==0)
			break;
	}
	http_close(http);
	output_verbose("socket %d closed",http->s);
}