owntone-server/src/httpd.h

166 lines
4.6 KiB
C

#ifndef __HTTPD_H__
#define __HTTPD_H__
#include <stdbool.h>
#include <regex.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
enum httpd_send_flags
{
HTTPD_SEND_NO_GZIP = (1 << 0),
};
/*
* Contains a parsed version of the URI httpd got. The URI may have been
* complete:
* scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
* or relative:
* [/path][?query][#fragment]
*
* We are interested in the path and the query, so they are disassembled to
* path_parts and ev_query. If the request is http://x:3689/foo/bar?key1=val1,
* then part_parts[1] is "foo", [2] is "bar" and the rest is null (the first
* element points to the copy of the path so it can be freed).
*
* The allocated strings are URI decoded.
*/
struct httpd_uri_parsed
{
const char *uri;
struct evhttp_uri *ev_uri;
struct evkeyvalq ev_query;
char *uri_decoded;
char *path;
char *path_parts[7];
};
/*
* A collection of pointers to request data that the reply handlers may need.
* Also has the function pointer to the reply handler and a pointer to a reply
* evbuffer.
*/
struct httpd_request {
// User-agent (if available)
const char *user_agent;
// The parsed request URI given to us by httpd_uri_parse
struct httpd_uri_parsed *uri_parsed;
// Shortcut to &uri_parsed->ev_query
struct evkeyvalq *query;
// http request struct (if available)
struct evhttp_request *req;
// Source IP address (ipv4 or ipv6) and port of the request (if available)
char *peer_address;
unsigned short peer_port;
// A pointer to extra data that the module handling the request might need
void *extra_data;
// Reply evbuffer
struct evbuffer *reply;
// A pointer to the handler that will process the request
int (*handler)(struct httpd_request *hreq);
};
/*
* Maps a regex of the request path to a handler of the request
*/
struct httpd_uri_map
{
char *regexp;
int (*handler)(struct httpd_request *hreq);
regex_t preg;
};
/*
* Helper to free the parsed uri struct
*/
void
httpd_uri_free(struct httpd_uri_parsed *parsed);
/*
* Parse an URI into the struct
*/
struct httpd_uri_parsed *
httpd_uri_parse(const char *uri);
/*
* Parse a request into the httpd_request struct. It can later be freed with
* free(), unless the module has allocated something to *extra_data. Note that
* the pointers in the returned struct are only valid as long as the inputs are
* still valid. If req is not null, then we will find the user-agent from the
* request headers, except if provided as an argument to this function.
*/
struct httpd_request *
httpd_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map);
void
httpd_stream_file(struct evhttp_request *req, int id);
/*
* Gzips an evbuffer
*
* @in in Data to be compressed
* @return Compressed data - must be freed by caller
*/
struct evbuffer *
httpd_gzip_deflate(struct evbuffer *in);
/*
* This wrapper around evhttp_send_reply should be used whenever a request may
* come from a browser. It will automatically gzip if feasible, but the caller
* may direct it not to. It will set CORS headers as appropriate. Should be
* thread safe.
*
* @in req The evhttp request struct
* @in code HTTP code, e.g. 200
* @in reason A brief explanation of the error - if NULL the standard meaning
of the error code will be used
* @in evbuf Data for the response body
* @in flags See flags above
*/
void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags);
/*
* This is a substitute for evhttp_send_error that should be used whenever an
* error may be returned to a browser. It will set CORS headers as appropriate,
* which is not possible with evhttp_send_error, because it clears the headers.
* Should be thread safe.
*
* @in req The evhttp request struct
* @in error HTTP code, e.g. 200
* @in reason A brief explanation of the error - if NULL the standard meaning
of the error code will be used
*/
void
httpd_send_error(struct evhttp_request *req, int error, const char *reason);
/*
* Redirects to /admin.html
*/
void
httpd_redirect_to_admin(struct evhttp_request *req);
/*
* Redirects to [uri]/index.html
*/
void
httpd_redirect_to_index(struct evhttp_request *req, const char *uri);
bool
httpd_admin_check_auth(struct evhttp_request *req);
int
httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passwd, const char *realm);
int
httpd_init(const char *webroot);
void
httpd_deinit(void);
#endif /* !__HTTPD_H__ */