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 package org.eclipse.jgit.lfs.server;
44
45 import static org.eclipse.jgit.lib.Constants.CHARSET;
46 import static org.apache.http.HttpStatus.SC_FORBIDDEN;
47 import static org.apache.http.HttpStatus.SC_INSUFFICIENT_STORAGE;
48 import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
49 import static org.apache.http.HttpStatus.SC_NOT_FOUND;
50 import static org.apache.http.HttpStatus.SC_OK;
51 import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
52 import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
53 import static org.apache.http.HttpStatus.SC_UNPROCESSABLE_ENTITY;
54 import static org.eclipse.jgit.lfs.lib.Constants.DOWNLOAD;
55 import static org.eclipse.jgit.lfs.lib.Constants.UPLOAD;
56 import static org.eclipse.jgit.lfs.lib.Constants.VERIFY;
57 import static org.eclipse.jgit.util.HttpSupport.HDR_AUTHORIZATION;
58
59 import java.io.BufferedReader;
60 import java.io.BufferedWriter;
61 import java.io.IOException;
62 import java.io.InputStreamReader;
63 import java.io.OutputStreamWriter;
64 import java.io.Reader;
65 import java.io.Writer;
66 import java.text.MessageFormat;
67 import java.util.List;
68
69 import javax.servlet.ServletException;
70 import javax.servlet.http.HttpServlet;
71 import javax.servlet.http.HttpServletRequest;
72 import javax.servlet.http.HttpServletResponse;
73
74 import org.eclipse.jgit.lfs.errors.LfsBandwidthLimitExceeded;
75 import org.eclipse.jgit.lfs.errors.LfsException;
76 import org.eclipse.jgit.lfs.errors.LfsInsufficientStorage;
77 import org.eclipse.jgit.lfs.errors.LfsRateLimitExceeded;
78 import org.eclipse.jgit.lfs.errors.LfsRepositoryNotFound;
79 import org.eclipse.jgit.lfs.errors.LfsRepositoryReadOnly;
80 import org.eclipse.jgit.lfs.errors.LfsUnauthorized;
81 import org.eclipse.jgit.lfs.errors.LfsUnavailable;
82 import org.eclipse.jgit.lfs.errors.LfsValidationError;
83 import org.eclipse.jgit.lfs.internal.LfsText;
84 import org.eclipse.jgit.lfs.server.internal.LfsGson;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
87
88
89
90
91
92
93
94
95 public abstract class LfsProtocolServlet extends HttpServlet {
96 private static Logger LOG = LoggerFactory
97 .getLogger(LfsProtocolServlet.class);
98
99 private static final long serialVersionUID = 1L;
100
101 private static final String CONTENTTYPE_VND_GIT_LFS_JSON =
102 "application/vnd.git-lfs+json; charset=utf-8";
103
104 private static final int SC_RATE_LIMIT_EXCEEDED = 429;
105
106 private static final int SC_BANDWIDTH_LIMIT_EXCEEDED = 509;
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 protected abstract LargeFileRepository getLargeFileRepository(
145 LfsRequest request, String path, String auth) throws LfsException;
146
147
148
149
150
151
152 protected static class LfsRequest {
153 private String operation;
154
155 private List<LfsObject> objects;
156
157
158
159
160
161
162 public String getOperation() {
163 return operation;
164 }
165
166
167
168
169
170
171 public List<LfsObject> getObjects() {
172 return objects;
173 }
174
175
176
177
178
179 public boolean isUpload() {
180 return operation.equals(UPLOAD);
181 }
182
183
184
185
186
187 public boolean isDownload() {
188 return operation.equals(DOWNLOAD);
189 }
190
191
192
193
194
195 public boolean isVerify() {
196 return operation.equals(VERIFY);
197 }
198 }
199
200
201 @Override
202 protected void doPost(HttpServletRequest req, HttpServletResponse res)
203 throws ServletException, IOException {
204 Writer w = new BufferedWriter(
205 new OutputStreamWriter(res.getOutputStream(), CHARSET));
206
207 Reader r = new BufferedReader(
208 new InputStreamReader(req.getInputStream(), CHARSET));
209 LfsRequest request = LfsGson.fromJson(r, LfsRequest.class);
210 String path = req.getPathInfo();
211
212 res.setContentType(CONTENTTYPE_VND_GIT_LFS_JSON);
213 LargeFileRepository repo = null;
214 try {
215 repo = getLargeFileRepository(request, path,
216 req.getHeader(HDR_AUTHORIZATION));
217 if (repo == null) {
218 String error = MessageFormat
219 .format(LfsText.get().lfsFailedToGetRepository, path);
220 LOG.error(error);
221 throw new LfsException(error);
222 }
223 res.setStatus(SC_OK);
224 TransferHandler handler = TransferHandler
225 .forOperation(request.operation, repo, request.objects);
226 LfsGson.toJson(handler.process(), w);
227 } catch (LfsValidationError e) {
228 sendError(res, w, SC_UNPROCESSABLE_ENTITY, e.getMessage());
229 } catch (LfsRepositoryNotFound e) {
230 sendError(res, w, SC_NOT_FOUND, e.getMessage());
231 } catch (LfsRepositoryReadOnly e) {
232 sendError(res, w, SC_FORBIDDEN, e.getMessage());
233 } catch (LfsRateLimitExceeded e) {
234 sendError(res, w, SC_RATE_LIMIT_EXCEEDED, e.getMessage());
235 } catch (LfsBandwidthLimitExceeded e) {
236 sendError(res, w, SC_BANDWIDTH_LIMIT_EXCEEDED, e.getMessage());
237 } catch (LfsInsufficientStorage e) {
238 sendError(res, w, SC_INSUFFICIENT_STORAGE, e.getMessage());
239 } catch (LfsUnavailable e) {
240 sendError(res, w, SC_SERVICE_UNAVAILABLE, e.getMessage());
241 } catch (LfsUnauthorized e) {
242 sendError(res, w, SC_UNAUTHORIZED, e.getMessage());
243 } catch (LfsException e) {
244 sendError(res, w, SC_INTERNAL_SERVER_ERROR, e.getMessage());
245 } finally {
246 w.flush();
247 }
248 }
249
250 private void sendError(HttpServletResponse rsp, Writer writer, int status,
251 String message) {
252 rsp.setStatus(status);
253 LfsGson.toJson(message, writer);
254 }
255 }