7
7
#include < nstd/Directory.hpp>
8
8
#include < nstd/Error.hpp>
9
9
#include < nstd/Process.hpp>
10
+ #include < nstd/HashMap.hpp>
11
+
12
+ #include " HttpRequest.hpp"
10
13
11
14
Worker::Worker (const Settings& settings, Socket& client, ICallback& callback)
12
15
: _settings(settings)
@@ -109,9 +112,9 @@ String getRequestUrl(const String& path)
109
112
return result;
110
113
}
111
114
112
- bool parseGetRequestPath (const String& path, String& url, String& repoUrl, String& repo, String& service)
115
+ bool parseGetRequestPath (const String& path, String& repoUrl, String& repo, String& service)
113
116
{
114
- url = getRequestUrl (path);
117
+ String url = getRequestUrl (path);
115
118
const char * x = url.find (" /info/refs?service=" );
116
119
if (!x)
117
120
return false ;
@@ -125,9 +128,9 @@ bool parseGetRequestPath(const String& path, String& url, String& repoUrl, Strin
125
128
}
126
129
127
130
128
- bool parsePostRequestPath (const String& path, String& url, String& repoUrl, String& repo, String& service)
131
+ bool parsePostRequestPath (const String& path, String& repoUrl, String& repo, String& service)
129
132
{
130
- url = getRequestUrl (path);
133
+ String url = getRequestUrl (path);
131
134
if (!url.endsWith (" /git-upload-pack" ))
132
135
return false ;
133
136
repoUrl = url.substr (0 , url.length () - 16 );
@@ -138,6 +141,35 @@ bool parsePostRequestPath(const String& path, String& url, String& repoUrl, Stri
138
141
return true ;
139
142
}
140
143
144
+ bool getAuth (const String& header, String& auth)
145
+ {
146
+ const char * authStart = header.find (" \r\n Authorization: " );
147
+ if (!authStart)
148
+ return false ;
149
+ authStart += 17 ;
150
+ const char * authEnd = String::find (authStart, " \r\n " );
151
+ if (!authEnd)
152
+ return false ;
153
+ auth = header.substr (authStart - (const char *)header, authEnd - authStart);
154
+ return true ;
155
+ }
156
+
157
+ bool isAccessible (const String& url, const String& auth)
158
+ {
159
+ HttpRequest httpRequest;
160
+ HashMap<String, String> headerFields;
161
+ if (!auth.isEmpty ())
162
+ headerFields.append (" Authorization" , auth);
163
+ Buffer data;
164
+ return httpRequest.get (url, data, headerFields, false );
165
+ }
166
+
167
+ void requestAuth (Socket& client)
168
+ {
169
+ String response = " HTTP/1.1 401 Unauthorized\r\n WWW-Authenticate: Basic realm=\"\"\r\n\r\n " ;
170
+ client.send ((const byte*)(const char *)response, response.length ());
171
+ }
172
+
141
173
}
142
174
143
175
void Worker::handleRequest ()
@@ -151,29 +183,40 @@ void Worker::handleRequest()
151
183
if (!parseHeader (header, method, path))
152
184
return ;
153
185
154
- // todo: auth
155
- // logic?
156
- // if auth is in header check auth with uplink
157
- // else check if uplink can be accessed without auth
158
- // else ? request auth
159
-
160
- if (method == " GET" )
161
- handleGetRequest (path);
162
- else if (method == " POST" )
163
- handlePostRequest (path, body);
164
- }
165
-
166
- void Worker::handleGetRequest (const String& path)
167
- {
168
- String requestUrl;
169
186
String repoUrl;
170
187
String repo;
171
188
String service;
172
- if (!parseGetRequestPath (path, requestUrl, repoUrl, repo, service))
189
+ if (method == " GET" )
190
+ {
191
+ if (!parseGetRequestPath (path, repoUrl, repo, service))
192
+ return ;
193
+ }
194
+ else if (method == " POST" )
195
+ {
196
+ if (!parsePostRequestPath (path, repoUrl, repo, service))
197
+ return ;
198
+ }
199
+ else
173
200
return ;
201
+
174
202
if (service != " git-upload-pack" )
175
203
return ;
176
204
205
+ String authCheckUrl = repoUrl + " /info/refs?service=git-upload-pack" ;
206
+ String auth;
207
+ getAuth (header, auth);
208
+ // todo: auth cache?
209
+ if (!isAccessible (authCheckUrl, auth))
210
+ return requestAuth (_client);
211
+
212
+ if (method == " GET" )
213
+ handleGetRequest (repoUrl, repo);
214
+ else if (method == " POST" )
215
+ handlePostRequest (repo, body);
216
+ }
217
+
218
+ void Worker::handleGetRequest (const String& repoUrl, const String& repo)
219
+ {
177
220
// todo: avoid concurrent git fetch !
178
221
179
222
// create cache dir
@@ -215,7 +258,7 @@ void Worker::handleGetRequest(const String& path)
215
258
return Log::errorf (" Could not launch command '%s': %s" , (const char *)command, (const char *)Error::getErrorString ());
216
259
217
260
String response = " HTTP/1.1 200 OK\r\n " ;
218
- response.append (String ( " Content-Type: application/x-" ) + service + " -advertisement\r\n " );
261
+ response.append (" Content-Type: application/x-git-upload-pack -advertisement\r\n " );
219
262
response.append (" Cache-Control: no-cache\r\n\r\n " );
220
263
response.append (" 001e# service=git-upload-pack\n 0000" );
221
264
if (_client.send ((const byte*)(const char *)response, response.length ()) != response.length ())
@@ -236,17 +279,8 @@ void Worker::handleGetRequest(const String& path)
236
279
}
237
280
}
238
281
239
- void Worker::handlePostRequest (const String& path , String& body)
282
+ void Worker::handlePostRequest (const String& repo , String& body)
240
283
{
241
- String requestUrl;
242
- String repoUrl;
243
- String repo;
244
- String service;
245
- if (!parsePostRequestPath (path, requestUrl, repoUrl, repo, service))
246
- return ;
247
- if (service != " git-upload-pack" )
248
- return ;
249
-
250
284
String cacheDir = _settings.cacheDir + " /" + repo;
251
285
252
286
{
@@ -261,7 +295,7 @@ void Worker::handlePostRequest(const String& path, String& body)
261
295
return ;
262
296
263
297
String response = " HTTP/1.1 200 OK\r\n " ;
264
- response.append (String ( " Content-Type: application/x-" ) + service + " -advertisement\r\n " );
298
+ response.append (" Content-Type: application/x-git-upload-pack -advertisement\r\n " );
265
299
response.append (" Cache-Control: no-cache\r\n\r\n " );
266
300
if (_client.send ((const byte*)(const char *)response, response.length ()) != response.length ())
267
301
return ;
0 commit comments