1
1
package langserver
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
5
6
"errors"
6
7
"fmt"
@@ -70,13 +71,13 @@ func (s *Service) Mount(r *mux.Router) {
70
71
r .Path ("/suggest" ).
71
72
HandlerFunc (WrapHandler (s .HandleGetSuggestion ))
72
73
r .Path ("/run" ).Methods (http .MethodPost ).
73
- HandlerFunc (WrapHandler (s .HandleRunCode , ValidateContentLength ))
74
+ HandlerFunc (WrapHandler (s .HandleRunCode ))
74
75
r .Path ("/compile" ).Methods (http .MethodPost ).
75
- HandlerFunc (WrapHandler (s .HandleCompile , ValidateContentLength ))
76
+ HandlerFunc (WrapHandler (s .HandleCompile ))
76
77
r .Path ("/format" ).Methods (http .MethodPost ).
77
- HandlerFunc (WrapHandler (s .HandleFormatCode , ValidateContentLength ))
78
+ HandlerFunc (WrapHandler (s .HandleFormatCode ))
78
79
r .Path ("/share" ).Methods (http .MethodPost ).
79
- HandlerFunc (WrapHandler (s .HandleShare , ValidateContentLength ))
80
+ HandlerFunc (WrapHandler (s .HandleShare ))
80
81
r .Path ("/snippet/{id}" ).Methods (http .MethodGet ).
81
82
HandlerFunc (WrapHandler (s .HandleGetSnippet ))
82
83
r .Path ("/backends/info" ).Methods (http .MethodGet ).
@@ -159,7 +160,7 @@ func (s *Service) HandleGetSuggestion(w http.ResponseWriter, r *http.Request) er
159
160
160
161
// HandleFormatCode handles goimports action
161
162
func (s * Service ) HandleFormatCode (w http.ResponseWriter , r * http.Request ) error {
162
- src , err := getPayloadFromRequest (r )
163
+ src , err := s . getPayloadFromRequest (r )
163
164
if err != nil {
164
165
return err
165
166
}
@@ -186,8 +187,8 @@ func (s *Service) HandleShare(w http.ResponseWriter, r *http.Request) error {
186
187
shareID , err := s .client .Share (r .Context (), r .Body )
187
188
defer r .Body .Close ()
188
189
if err != nil {
189
- if errors . Is (err , goplay . ErrSnippetTooLarge ) {
190
- return NewHTTPError ( http . StatusRequestEntityTooLarge , err )
190
+ if isContentLengthError (err ) {
191
+ return ErrSnippetTooLarge
191
192
}
192
193
193
194
s .log .Error ("failed to share code: " , err )
@@ -225,7 +226,7 @@ func (s *Service) HandleGetSnippet(w http.ResponseWriter, r *http.Request) error
225
226
// HandleRunCode handles code run
226
227
func (s * Service ) HandleRunCode (w http.ResponseWriter , r * http.Request ) error {
227
228
ctx := r .Context ()
228
- src , err := getPayloadFromRequest (r )
229
+ src , err := s . getPayloadFromRequest (r )
229
230
if err != nil {
230
231
return err
231
232
}
@@ -304,17 +305,15 @@ func (s *Service) HandleArtifactRequest(w http.ResponseWriter, r *http.Request)
304
305
w .Header ().Set ("Content-Length" , contentLength )
305
306
w .Header ().Set (rawContentLengthHeader , contentLength )
306
307
307
- n , err := io .Copy (w , data )
308
308
defer data .Close ()
309
- if err != nil {
309
+ if _ , err := io . Copy ( w , data ); err != nil {
310
310
s .log .Errorw ("failed to send artifact" ,
311
311
"artifactID" , artifactId ,
312
312
"err" , err ,
313
313
)
314
314
return err
315
315
}
316
316
317
- w .Header ().Set ("Content-Length" , strconv .FormatInt (n , 10 ))
318
317
return nil
319
318
}
320
319
@@ -329,7 +328,7 @@ func (s *Service) HandleCompile(w http.ResponseWriter, r *http.Request) error {
329
328
return NewHTTPError (http .StatusTooManyRequests , err )
330
329
}
331
330
332
- src , err := getPayloadFromRequest (r )
331
+ src , err := s . getPayloadFromRequest (r )
333
332
if err != nil {
334
333
return err
335
334
}
@@ -391,8 +390,8 @@ func backendFromRequest(r *http.Request) (goplay.Backend, error) {
391
390
func (s * Service ) goImportsCode (ctx context.Context , src []byte , backend goplay.Backend ) ([]byte , bool , error ) {
392
391
resp , err := s .client .GoImports (ctx , src , backend )
393
392
if err != nil {
394
- if errors . Is (err , goplay . ErrSnippetTooLarge ) {
395
- return nil , false , NewHTTPError ( http . StatusRequestEntityTooLarge , err )
393
+ if isContentLengthError (err ) {
394
+ return nil , false , ErrSnippetTooLarge
396
395
}
397
396
398
397
s .log .Error (err )
@@ -406,3 +405,31 @@ func (s *Service) goImportsCode(ctx context.Context, src []byte, backend goplay.
406
405
changed := resp .Body != string (src )
407
406
return []byte (resp .Body ), changed , nil
408
407
}
408
+
409
+ func (s * Service ) getPayloadFromRequest (r * http.Request ) ([]byte , error ) {
410
+ // see: https://github.com/golang/playground/blob/master/share.go#L69
411
+ var buff bytes.Buffer
412
+ buff .Grow (goplay .MaxSnippetSize )
413
+
414
+ defer r .Body .Close ()
415
+ _ , err := io .Copy (& buff , io .LimitReader (r .Body , goplay .MaxSnippetSize + 1 ))
416
+ if err != nil {
417
+ return nil , Errorf (http .StatusBadGateway , "failed to read request: %w" , err )
418
+ }
419
+
420
+ if buff .Len () > goplay .MaxSnippetSize {
421
+ return nil , ErrSnippetTooLarge
422
+ }
423
+
424
+ return buff .Bytes (), nil
425
+ }
426
+
427
+ func isContentLengthError (err error ) bool {
428
+ if httpErr , ok := goplay .IsHTTPError (err ); ok {
429
+ if httpErr .StatusCode == http .StatusRequestEntityTooLarge {
430
+ return true
431
+ }
432
+ }
433
+
434
+ return false
435
+ }
0 commit comments