Skip to content

Commit 0e25b73

Browse files
authored
Merge pull request #15 from x1unix/fix/format-error
Fix error on code format
2 parents c9aecc2 + ba7888e commit 0e25b73

File tree

12 files changed

+572
-455
lines changed

12 files changed

+572
-455
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ UI := ./web
33
TARGET := ./target
44
LISTEN_ADDR := 0.0.0.0:8000
55
DEBUG ?= true
6+
GTAG ?= # Set GTAG to enable Google Analytics
67

78
.PHONY:all
89
all: build
@@ -16,5 +17,5 @@ run:
1617

1718
.PHONY:ui
1819
ui:
19-
@cd $(UI) && REACT_APP_LANG_SERVER=http://$(LISTEN_ADDR) REACT_APP_VERSION=testing yarn start
20+
@cd $(UI) && REACT_APP_LANG_SERVER=http://$(LISTEN_ADDR) REACT_APP_GTAG=$(GTAG) REACT_APP_VERSION=testing yarn start
2021

data/packages.json

Lines changed: 318 additions & 310 deletions
Large diffs are not rendered by default.

pkg/compiler/error.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,3 @@ func (e *BuildError) Error() string {
1111
func newBuildError(msg string) *BuildError {
1212
return &BuildError{message: msg}
1313
}
14-
15-
//func newBuildError(errPipe io.ReadCloser, baseErr error) *BuildError {
16-
// data, err := ioutil.ReadAll(errPipe)
17-
// if err != nil {
18-
// return &BuildError{message: baseErr.Error()}
19-
// }
20-
//
21-
// return &BuildError{message: string(data)}
22-
//}

pkg/goplay/methods.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"go.uber.org/zap"
87
"io"
98
"io/ioutil"
109
"net/http"
1110
"net/url"
11+
12+
"go.uber.org/zap"
1213
)
1314

1415
func ValidateContentLength(itemLen int) error {
@@ -89,11 +90,8 @@ func Compile(ctx context.Context, src []byte) (*CompileResponse, error) {
8990

9091
dest := &CompileResponse{}
9192
if err := json.Unmarshal(resp, dest); err != nil {
92-
zap.S().Errorw("Compiler response is not JSON",
93-
"err", err,
94-
"resp", string(resp),
95-
)
96-
return nil, fmt.Errorf("failed to decode upstream server response: %s", err)
93+
// return response text as errors
94+
return nil, fmt.Errorf("error from %q: %s", goPlayURL, string(resp))
9795
}
9896

9997
return dest, err

pkg/langserver/errors.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package langserver
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
)
7+
8+
// HTTPError is HTTP response error
9+
type HTTPError struct {
10+
code int
11+
parent error
12+
}
13+
14+
// Error implements error
15+
func (err *HTTPError) Error() string {
16+
return fmt.Sprintf("%s: %s", http.StatusText(err.code), err.parent)
17+
}
18+
19+
// Unwrap implements error
20+
func (err *HTTPError) Unwrap() error {
21+
return err.parent
22+
}
23+
24+
func (err *HTTPError) WriteResponse(rw http.ResponseWriter) {
25+
resp := ErrorResponse{code: err.code, Error: err.parent.Error()}
26+
resp.Write(rw)
27+
}
28+
29+
func NewHTTPError(code int, err error) *HTTPError {
30+
return &HTTPError{code: code, parent: err}
31+
}
32+
33+
func Errorf(code int, format string, args ...interface{}) *HTTPError {
34+
return NewHTTPError(code, fmt.Errorf(format, args...))
35+
}

pkg/langserver/middleware.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package langserver
2+
3+
import (
4+
"github.com/x1unix/go-playground/pkg/goplay"
5+
"net/http"
6+
)
7+
8+
type HandlerFunc func(http.ResponseWriter, *http.Request) error
9+
type GuardFn func(r *http.Request) error
10+
11+
func WrapHandler(h HandlerFunc, guards ...GuardFn) http.HandlerFunc {
12+
return func(w http.ResponseWriter, r *http.Request) {
13+
if len(guards) == 0 {
14+
for _, guardFn := range guards {
15+
if err := guardFn(r); err != nil {
16+
handleError(err, w)
17+
return
18+
}
19+
}
20+
}
21+
22+
handleError(h(w, r), w)
23+
}
24+
}
25+
26+
func ValidateContentLength(r *http.Request) error {
27+
if err := goplay.ValidateContentLength(int(r.ContentLength)); err != nil {
28+
return NewHTTPError(http.StatusRequestEntityTooLarge, err)
29+
}
30+
31+
return nil
32+
}
33+
34+
func handleError(err error, w http.ResponseWriter) {
35+
if err == nil {
36+
return
37+
}
38+
39+
if httpErr, ok := err.(*HTTPError); ok {
40+
httpErr.WriteResponse(w)
41+
return
42+
}
43+
44+
resp := NewErrorResponse(err)
45+
resp.Write(w)
46+
}

pkg/langserver/request.go

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package langserver
22

33
import (
4+
"context"
45
"encoding/json"
5-
"fmt"
6+
"io/ioutil"
67
"net/http"
8+
"strconv"
79
"strings"
810

11+
"github.com/x1unix/go-playground/pkg/analyzer"
912
"github.com/x1unix/go-playground/pkg/goplay"
10-
1113
"go.uber.org/zap"
12-
13-
"github.com/x1unix/go-playground/pkg/analyzer"
1414
)
1515

1616
type SnippetResponse struct {
@@ -39,19 +39,11 @@ type ErrorResponse struct {
3939
Error string `json:"error"`
4040
}
4141

42-
func NewErrorResponse(err error) ErrorResponse {
43-
return ErrorResponse{Error: err.Error(), code: http.StatusInternalServerError}
44-
}
45-
46-
// Errorf creates error response
47-
func Errorf(code int, format string, args ...interface{}) ErrorResponse {
48-
return ErrorResponse{
49-
code: code,
50-
Error: fmt.Sprintf(format, args...),
51-
}
42+
func NewErrorResponse(err error) *ErrorResponse {
43+
return &ErrorResponse{Error: err.Error(), code: http.StatusInternalServerError}
5244
}
5345

54-
func (r ErrorResponse) Write(w http.ResponseWriter) http.ResponseWriter {
46+
func (r *ErrorResponse) Write(w http.ResponseWriter) http.ResponseWriter {
5547
w.Header().Add("Content-Type", "application/json")
5648
w.WriteHeader(r.code)
5749
if err := json.NewEncoder(w).Encode(r); err != nil {
@@ -90,3 +82,52 @@ func WriteJSON(w http.ResponseWriter, i interface{}) {
9082
w.Write(data)
9183
return
9284
}
85+
86+
// goImportsCode reads code from request and performs "goimports" on it
87+
// if any error occurs, it sends error response to client and closes connection
88+
//
89+
// if "format" url query param is undefined or set to "false", just returns code as is
90+
func goImportsCode(ctx context.Context, src []byte) ([]byte, bool, error) {
91+
resp, err := goplay.GoImports(ctx, src)
92+
if err != nil {
93+
if err == goplay.ErrSnippetTooLarge {
94+
return nil, false, NewHTTPError(http.StatusRequestEntityTooLarge, err)
95+
}
96+
97+
return nil, false, err
98+
}
99+
100+
if err = resp.HasError(); err != nil {
101+
return nil, false, err
102+
}
103+
104+
changed := resp.Body != string(src)
105+
return []byte(resp.Body), changed, nil
106+
}
107+
108+
func shouldFormatCode(r *http.Request) (bool, error) {
109+
val := r.URL.Query().Get(formatQueryParam)
110+
if val == "" {
111+
return false, nil
112+
}
113+
114+
boolVal, err := strconv.ParseBool(val)
115+
if err != nil {
116+
return false, Errorf(
117+
http.StatusBadRequest,
118+
"invalid %q query parameter value (expected boolean)", formatQueryParam,
119+
)
120+
}
121+
122+
return boolVal, nil
123+
}
124+
125+
func getPayloadFromRequest(r *http.Request) ([]byte, error) {
126+
src, err := ioutil.ReadAll(r.Body)
127+
if err != nil {
128+
return nil, Errorf(http.StatusBadGateway, "failed to read request: %s", err)
129+
}
130+
131+
r.Body.Close()
132+
return src, nil
133+
}

0 commit comments

Comments
 (0)