014da394ef9edf1918efdb8ff97925420b847812
[platform/upstream/libsoup.git] / tests / proxy-test.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9
10 #include "libsoup/soup.h"
11 #include "test-utils.h"
12
13 typedef struct {
14         const char *explanation;
15         const char *url;
16         const guint final_status;
17 } SoupProxyTest;
18
19 static SoupProxyTest tests[] = {
20         { "GET -> 200", "", SOUP_STATUS_OK },
21         { "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND },
22         { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK },
23         { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED },
24         { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN },
25 };
26 static int ntests = sizeof (tests) / sizeof (tests[0]);
27
28 #define HTTP_SERVER    "http://127.0.0.1:47524"
29 #define HTTPS_SERVER   "https://127.0.0.1:47525"
30
31 enum {
32         SIMPLE_PROXY,
33         AUTH_PROXY,
34         UNAUTH_PROXY
35 };
36 static const char *proxies[] = {
37         "http://127.0.0.1:47526",
38         "http://127.0.0.1:47527",
39         "http://127.0.0.1:47528"
40 };
41 static const char *proxy_names[] = {
42         "simple proxy",
43         "authenticated proxy",
44         "unauthenticatable-to proxy"
45 };
46
47 static void
48 authenticate (SoupSession *session, SoupMessage *msg,
49               SoupAuth *auth, gboolean retrying, gpointer data)
50 {
51         if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
52                 if (soup_auth_is_for_proxy (auth)) {
53                         debug_printf (1, "  got proxy auth object for 401!\n");
54                         errors++;
55                 }
56         } else if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) {
57                 if (!soup_auth_is_for_proxy (auth)) {
58                         debug_printf (1, "  got regular auth object for 407!\n");
59                         errors++;
60                 }
61         } else {
62                 debug_printf (1, "  got authenticate signal with status %d\n",
63                               msg->status_code);
64                 errors++;
65         }
66
67         if (!retrying)
68                 soup_auth_authenticate (auth, "user1", "realm1");
69 }
70
71 static void
72 set_close_on_connect (SoupSession *session, SoupMessage *msg,
73                       SoupSocket *sock, gpointer user_data)
74 {
75         /* This is used to test that we can handle the server closing
76          * the connection when returning a 407 in response to a
77          * CONNECT. (Rude!)
78          */
79         if (msg->method == SOUP_METHOD_CONNECT) {
80                 soup_message_headers_append (msg->request_headers,
81                                              "Connection", "close");
82         }
83 }
84
85 static void
86 test_url (const char *url, int proxy, guint expected,
87           gboolean sync, gboolean close)
88 {
89         SoupSession *session;
90         SoupURI *proxy_uri;
91         SoupMessage *msg;
92
93         if (!tls_available && g_str_has_prefix (url, "https:"))
94                 return;
95
96         debug_printf (1, "  GET %s via %s%s\n", url, proxy_names[proxy],
97                       close ? " (with Connection: close)" : "");
98         if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN)
99                 expected = SOUP_STATUS_PROXY_UNAUTHORIZED;
100
101         /* We create a new session for each request to ensure that
102          * connections/auth aren't cached between tests.
103          */
104         proxy_uri = soup_uri_new (proxies[proxy]);
105         session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC,
106                                          SOUP_SESSION_PROXY_URI, proxy_uri,
107                                          NULL);
108         soup_uri_free (proxy_uri);
109         g_signal_connect (session, "authenticate",
110                           G_CALLBACK (authenticate), NULL);
111         if (close) {
112                 g_signal_connect (session, "request-started",
113                                   G_CALLBACK (set_close_on_connect), NULL);
114         }
115
116         msg = soup_message_new (SOUP_METHOD_GET, url);
117         if (!msg) {
118                 fprintf (stderr, "proxy-test: Could not parse URI\n");
119                 exit (1);
120         }
121
122         soup_session_send_message (session, msg);
123
124         debug_printf (1, "  %d %s\n", msg->status_code, msg->reason_phrase);
125         if (msg->status_code != expected) {
126                 debug_printf (1, "  EXPECTED %d!\n", expected);
127                 errors++;
128         }
129
130         g_object_unref (msg);
131         soup_test_session_abort_unref (session);
132 }
133
134 static void
135 run_test (int i, gboolean sync)
136 {
137         char *http_url, *https_url;
138
139         debug_printf (1, "Test %d: %s (%s)\n", i + 1, tests[i].explanation,
140                       sync ? "sync" : "async");
141
142         if (!strncmp (tests[i].url, "http", 4)) {
143                 http_url = g_strdup (tests[i].url);
144                 https_url = g_strdup_printf ("https%s", tests[i].url + 4);
145         } else {
146                 http_url = g_strconcat (HTTP_SERVER, tests[i].url, NULL);
147                 https_url = g_strconcat (HTTPS_SERVER, tests[i].url, NULL);
148         }
149         test_url (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
150         test_url (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
151         test_url (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
152         test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
153         test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE);
154         test_url (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
155         test_url (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
156
157         g_free (http_url);
158         g_free (https_url);
159
160         debug_printf (1, "\n");
161 }
162
163 static void
164 server_callback (SoupServer *server, SoupMessage *msg,
165                  const char *path, GHashTable *query,
166                  SoupClientContext *context, gpointer data)
167 {
168         SoupURI *uri = soup_message_get_uri (msg);
169
170         soup_message_set_status (msg, uri->fragment ? SOUP_STATUS_BAD_REQUEST : SOUP_STATUS_OK);
171 }
172
173 static void
174 do_proxy_fragment_test (SoupURI *base_uri)
175 {
176         SoupSession *session;
177         SoupURI *proxy_uri, *req_uri;
178         SoupMessage *msg;
179
180         debug_printf (1, "\nTesting request with fragment via proxy\n");
181
182         proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]);
183         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
184                                          SOUP_SESSION_PROXY_URI, proxy_uri,
185                                          NULL);
186         soup_uri_free (proxy_uri);
187
188         req_uri = soup_uri_new_with_base (base_uri, "/#foo");
189         msg = soup_message_new_from_uri (SOUP_METHOD_GET, req_uri);
190         soup_uri_free (req_uri);
191         soup_session_send_message (session, msg);
192
193         if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
194                 debug_printf (1, "  unexpected status %d %s!\n",
195                               msg->status_code, msg->reason_phrase);
196                 errors++;
197         }
198
199         g_object_unref (msg);
200         soup_test_session_abort_unref (session);
201 }
202
203 int
204 main (int argc, char **argv)
205 {
206         SoupServer *server;
207         SoupURI *base_uri;
208         int i;
209
210         test_init (argc, argv, NULL);
211         apache_init ();
212
213         for (i = 0; i < ntests; i++) {
214                 run_test (i, FALSE);
215                 run_test (i, TRUE);
216         }
217
218         server = soup_test_server_new (TRUE);
219         soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
220         base_uri = soup_uri_new ("http://127.0.0.1/");
221         soup_uri_set_port (base_uri, soup_server_get_port (server));
222
223         do_proxy_fragment_test (base_uri);
224
225         soup_uri_free (base_uri);
226         soup_test_server_quit_unref (server);
227
228         test_cleanup ();
229         return errors != 0;
230 }