1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.lfs.server;
11
12 import static java.nio.charset.StandardCharsets.UTF_8;
13 import static org.apache.http.HttpStatus.SC_FORBIDDEN;
14 import static org.apache.http.HttpStatus.SC_INSUFFICIENT_STORAGE;
15 import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
16 import static org.apache.http.HttpStatus.SC_NOT_FOUND;
17 import static org.apache.http.HttpStatus.SC_OK;
18 import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
19 import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
20 import static org.apache.http.HttpStatus.SC_UNPROCESSABLE_ENTITY;
21 import static org.eclipse.jgit.lfs.lib.Constants.DOWNLOAD;
22 import static org.eclipse.jgit.lfs.lib.Constants.UPLOAD;
23 import static org.eclipse.jgit.lfs.lib.Constants.VERIFY;
24 import static org.eclipse.jgit.util.HttpSupport.HDR_AUTHORIZATION;
25
26 import java.io.BufferedReader;
27 import java.io.BufferedWriter;
28 import java.io.IOException;
29 import java.io.InputStreamReader;
30 import java.io.OutputStreamWriter;
31 import java.io.Reader;
32 import java.io.Writer;
33 import java.text.MessageFormat;
34 import java.util.List;
35
36 import javax.servlet.ServletException;
37 import javax.servlet.http.HttpServlet;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40
41 import org.eclipse.jgit.lfs.errors.LfsBandwidthLimitExceeded;
42 import org.eclipse.jgit.lfs.errors.LfsException;
43 import org.eclipse.jgit.lfs.errors.LfsInsufficientStorage;
44 import org.eclipse.jgit.lfs.errors.LfsRateLimitExceeded;
45 import org.eclipse.jgit.lfs.errors.LfsRepositoryNotFound;
46 import org.eclipse.jgit.lfs.errors.LfsRepositoryReadOnly;
47 import org.eclipse.jgit.lfs.errors.LfsUnauthorized;
48 import org.eclipse.jgit.lfs.errors.LfsUnavailable;
49 import org.eclipse.jgit.lfs.errors.LfsValidationError;
50 import org.eclipse.jgit.lfs.internal.LfsText;
51 import org.eclipse.jgit.lfs.server.internal.LfsGson;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55
56
57
58
59
60
61
62 public abstract class LfsProtocolServlet extends HttpServlet {
63 private static final Logger LOG = LoggerFactory
64 .getLogger(LfsProtocolServlet.class);
65
66 private static final long serialVersionUID = 1L;
67
68 private static final String CONTENTTYPE_VND_GIT_LFS_JSON =
69 "application/vnd.git-lfs+json; charset=utf-8";
70
71 private static final int SC_RATE_LIMIT_EXCEEDED = 429;
72
73 private static final int SC_BANDWIDTH_LIMIT_EXCEEDED = 509;
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 protected abstract LargeFileRepository getLargeFileRepository(
112 LfsRequest request, String path, String auth) throws LfsException;
113
114
115
116
117
118
119 protected static class LfsRequest {
120 private String operation;
121
122 private List<LfsObject> objects;
123
124
125
126
127
128
129 public String getOperation() {
130 return operation;
131 }
132
133
134
135
136
137
138 public List<LfsObject> getObjects() {
139 return objects;
140 }
141
142
143
144
145
146 public boolean isUpload() {
147 return operation.equals(UPLOAD);
148 }
149
150
151
152
153
154 public boolean isDownload() {
155 return operation.equals(DOWNLOAD);
156 }
157
158
159
160
161
162 public boolean isVerify() {
163 return operation.equals(VERIFY);
164 }
165 }
166
167
168 @Override
169 protected void doPost(HttpServletRequest req, HttpServletResponse res)
170 throws ServletException, IOException {
171 Writer w = new BufferedWriter(
172 new OutputStreamWriter(res.getOutputStream(), UTF_8));
173
174 Reader r = new BufferedReader(
175 new InputStreamReader(req.getInputStream(), UTF_8));
176 LfsRequest request = LfsGson.fromJson(r, LfsRequest.class);
177 String path = req.getPathInfo();
178
179 res.setContentType(CONTENTTYPE_VND_GIT_LFS_JSON);
180 LargeFileRepository repo = null;
181 try {
182 repo = getLargeFileRepository(request, path,
183 req.getHeader(HDR_AUTHORIZATION));
184 if (repo == null) {
185 String error = MessageFormat
186 .format(LfsText.get().lfsFailedToGetRepository, path);
187 LOG.error(error);
188 throw new LfsException(error);
189 }
190 res.setStatus(SC_OK);
191 TransferHandler handler = TransferHandler
192 .forOperation(request.operation, repo, request.objects);
193 LfsGson.toJson(handler.process(), w);
194 } catch (LfsValidationError e) {
195 sendError(res, w, SC_UNPROCESSABLE_ENTITY, e.getMessage());
196 } catch (LfsRepositoryNotFound e) {
197 sendError(res, w, SC_NOT_FOUND, e.getMessage());
198 } catch (LfsRepositoryReadOnly e) {
199 sendError(res, w, SC_FORBIDDEN, e.getMessage());
200 } catch (LfsRateLimitExceeded e) {
201 sendError(res, w, SC_RATE_LIMIT_EXCEEDED, e.getMessage());
202 } catch (LfsBandwidthLimitExceeded e) {
203 sendError(res, w, SC_BANDWIDTH_LIMIT_EXCEEDED, e.getMessage());
204 } catch (LfsInsufficientStorage e) {
205 sendError(res, w, SC_INSUFFICIENT_STORAGE, e.getMessage());
206 } catch (LfsUnavailable e) {
207 sendError(res, w, SC_SERVICE_UNAVAILABLE, e.getMessage());
208 } catch (LfsUnauthorized e) {
209 sendError(res, w, SC_UNAUTHORIZED, e.getMessage());
210 } catch (LfsException e) {
211 sendError(res, w, SC_INTERNAL_SERVER_ERROR, e.getMessage());
212 } finally {
213 w.flush();
214 }
215 }
216
217 private void sendError(HttpServletResponse rsp, Writer writer, int status,
218 String message) {
219 rsp.setStatus(status);
220 LfsGson.toJson(message, writer);
221 }
222 }