summaryrefslogtreecommitdiff
path: root/src/transports/httpclient.h
blob: 6d0ef9edbf4bb2022c039a740561c1f89e35f645 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#ifndef INCLUDE_transports_httpclient_h__
#define INCLUDE_transports_httpclient_h__

#include "common.h"
#include "net.h"

#define GIT_HTTP_STATUS_CONTINUE                      100
#define GIT_HTTP_STATUS_OK                            200
#define GIT_HTTP_MOVED_PERMANENTLY                    301
#define GIT_HTTP_FOUND                                302
#define GIT_HTTP_SEE_OTHER                            303
#define GIT_HTTP_TEMPORARY_REDIRECT                   307
#define GIT_HTTP_PERMANENT_REDIRECT                   308
#define GIT_HTTP_STATUS_UNAUTHORIZED                  401
#define GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED 407

typedef struct git_http_client git_http_client;

/** Method for the HTTP request */
typedef enum {
	GIT_HTTP_METHOD_GET,
	GIT_HTTP_METHOD_POST,
	GIT_HTTP_METHOD_CONNECT
} git_http_method;

/** An HTTP request */
typedef struct {
	git_http_method method;            /**< Method for the request */
	git_net_url *url;                  /**< Full request URL */
	git_net_url *proxy;                /**< Proxy to use */

	/* Headers */
	const char *accept;                /**< Contents of the Accept header */
	const char *content_type;          /**< Content-Type header (for POST) */
	git_credential *credentials;       /**< Credentials to authenticate with */
	git_credential *proxy_credentials; /**< Credentials for proxy */
	git_strarray *custom_headers;      /**< Additional headers to deliver */

	/* To POST a payload, either set content_length OR set chunked. */
	size_t content_length;             /**< Length of the POST body */
	unsigned chunked : 1,              /**< Post with chunking */
	         expect_continue : 1;      /**< Use expect/continue negotiation */
} git_http_request;

typedef struct {
	int status;

	/* Headers */
	char *content_type;
	size_t content_length;
	char *location;

	/* Authentication headers */
	unsigned server_auth_schemetypes; /**< Schemes requested by remote */
	unsigned server_auth_credtypes;   /**< Supported cred types for remote */

	unsigned proxy_auth_schemetypes;  /**< Schemes requested by proxy */
	unsigned proxy_auth_credtypes;    /**< Supported cred types for proxy */

	unsigned chunked : 1,             /**< Response body is chunked */
	         resend_credentials : 1;  /**< Resend with authentication */
} git_http_response;

typedef struct {
	/** Certificate check callback for the remote */
	git_transport_certificate_check_cb server_certificate_check_cb;
	void *server_certificate_check_payload;

	/** Certificate check callback for the proxy */
	git_transport_certificate_check_cb proxy_certificate_check_cb;
	void *proxy_certificate_check_payload;
} git_http_client_options;

/**
 * Create a new httpclient instance with the given options.
 *
 * @param out pointer to receive the new instance
 * @param opts options to create the client with or NULL for defaults
 */
extern int git_http_client_new(
	git_http_client **out,
	git_http_client_options *opts);

/*
 * Sends a request to the host specified by the request URL.  If the
 * method is POST, either the content_length or the chunked flag must
 * be specified.  The body should be provided in subsequent calls to
 * git_http_client_send_body.
 *
 * @param client the client to write the request to
 * @param request the request to send
 */
extern int git_http_client_send_request(
	git_http_client *client,
	git_http_request *request);

/*
 * After sending a request, there may already be a response to read --
 * either because there was a non-continue response to an expect: continue
 * request, or because the server pipelined a response to us before we even
 * sent the request.  Examine the state.
 *
 * @param client the client to examine
 * @return true if there's already a response to read, false otherwise
 */
extern bool git_http_client_has_response(git_http_client *client);

/**
 * Sends the given buffer to the remote as part of the request body.  The
 * request must have specified either a content_length or the chunked flag.
 *
 * @param client the client to write the request body to
 * @param buffer the request body
 * @param buffer_len number of bytes of the buffer to send
 */
extern int git_http_client_send_body(
	git_http_client *client,
	const char *buffer,
	size_t buffer_len);

/**
 * Reads the headers of a response to a request.  This will consume the
 * entirety of the headers of a response from the server.  The body (if any)
 * can be read by calling git_http_client_read_body.  Callers must free
 * the response with git_http_response_dispose.
 *
 * @param response pointer to the response object to fill
 * @param client the client to read the response from
 */
extern int git_http_client_read_response(
	git_http_response *response,
	git_http_client *client);

/**
 * Reads some or all of the body of a response.  At most buffer_size (or
 * INT_MAX) bytes will be read and placed into the buffer provided.  The
 * number of bytes read will be returned, or 0 to indicate that the end of
 * the body has been read.
 *
 * @param client the client to read the response from
 * @param buffer pointer to the buffer to fill
 * @param buffer_size the maximum number of bytes to read
 * @return the number of bytes read, 0 on end of body, or error code
 */
extern int git_http_client_read_body(
	git_http_client *client,
	char *buffer,
	size_t buffer_size);

/**
 * Reads all of the (remainder of the) body of the response and ignores it.
 * None of the data from the body will be returned to the caller.
 *
 * @param client the client to read the response from
 * @return 0 or an error code
 */
extern int git_http_client_skip_body(git_http_client *client);

/**
 * Examines the status code of the response to determine if it is a
 * redirect of any type (eg, 301, 302, etc).
 *
 * @param response the response to inspect
 * @return true if the response is a redirect, false otherwise
 */
extern bool git_http_response_is_redirect(git_http_response *response);

/**
 * Frees any memory associated with the response.
 *
 * @param response the response to free
 */
extern void git_http_response_dispose(git_http_response *response);

/**
 * Frees any memory associated with the client.  If any sockets are open,
 * they will be closed.
 *
 * @param client the client to free
 */
extern void git_http_client_free(git_http_client *client);

#endif