Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ UI := ./web
TARGET := ./target
LISTEN_ADDR := 0.0.0.0:8000
DEBUG ?= true
GTAG ?= # Set GTAG to enable Google Analytics

.PHONY:all
all: build
Expand All @@ -16,5 +17,5 @@ run:

.PHONY:ui
ui:
@cd $(UI) && REACT_APP_LANG_SERVER=http://$(LISTEN_ADDR) REACT_APP_VERSION=testing yarn start
@cd $(UI) && REACT_APP_LANG_SERVER=http://$(LISTEN_ADDR) REACT_APP_GTAG=$(GTAG) REACT_APP_VERSION=testing yarn start

628 changes: 318 additions & 310 deletions data/packages.json

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions pkg/compiler/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,3 @@ func (e *BuildError) Error() string {
func newBuildError(msg string) *BuildError {
return &BuildError{message: msg}
}

//func newBuildError(errPipe io.ReadCloser, baseErr error) *BuildError {
// data, err := ioutil.ReadAll(errPipe)
// if err != nil {
// return &BuildError{message: baseErr.Error()}
// }
//
// return &BuildError{message: string(data)}
//}
10 changes: 4 additions & 6 deletions pkg/goplay/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"context"
"encoding/json"
"fmt"
"go.uber.org/zap"
"io"
"io/ioutil"
"net/http"
"net/url"

"go.uber.org/zap"
)

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

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

return dest, err
Expand Down
35 changes: 35 additions & 0 deletions pkg/langserver/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package langserver

import (
"fmt"
"net/http"
)

// HTTPError is HTTP response error
type HTTPError struct {
code int
parent error
}

// Error implements error
func (err *HTTPError) Error() string {
return fmt.Sprintf("%s: %s", http.StatusText(err.code), err.parent)
}

// Unwrap implements error
func (err *HTTPError) Unwrap() error {
return err.parent
}

func (err *HTTPError) WriteResponse(rw http.ResponseWriter) {
resp := ErrorResponse{code: err.code, Error: err.parent.Error()}
resp.Write(rw)
}

func NewHTTPError(code int, err error) *HTTPError {
return &HTTPError{code: code, parent: err}
}

func Errorf(code int, format string, args ...interface{}) *HTTPError {
return NewHTTPError(code, fmt.Errorf(format, args...))
}
46 changes: 46 additions & 0 deletions pkg/langserver/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package langserver

import (
"github.com/x1unix/go-playground/pkg/goplay"
"net/http"
)

type HandlerFunc func(http.ResponseWriter, *http.Request) error
type GuardFn func(r *http.Request) error

func WrapHandler(h HandlerFunc, guards ...GuardFn) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if len(guards) == 0 {
for _, guardFn := range guards {
if err := guardFn(r); err != nil {
handleError(err, w)
return
}
}
}

handleError(h(w, r), w)
}
}

func ValidateContentLength(r *http.Request) error {
if err := goplay.ValidateContentLength(int(r.ContentLength)); err != nil {
return NewHTTPError(http.StatusRequestEntityTooLarge, err)
}

return nil
}

func handleError(err error, w http.ResponseWriter) {
if err == nil {
return
}

if httpErr, ok := err.(*HTTPError); ok {
httpErr.WriteResponse(w)
return
}

resp := NewErrorResponse(err)
resp.Write(w)
}
71 changes: 56 additions & 15 deletions pkg/langserver/request.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package langserver

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"

"github.com/x1unix/go-playground/pkg/analyzer"
"github.com/x1unix/go-playground/pkg/goplay"

"go.uber.org/zap"

"github.com/x1unix/go-playground/pkg/analyzer"
)

type SnippetResponse struct {
Expand Down Expand Up @@ -39,19 +39,11 @@ type ErrorResponse struct {
Error string `json:"error"`
}

func NewErrorResponse(err error) ErrorResponse {
return ErrorResponse{Error: err.Error(), code: http.StatusInternalServerError}
}

// Errorf creates error response
func Errorf(code int, format string, args ...interface{}) ErrorResponse {
return ErrorResponse{
code: code,
Error: fmt.Sprintf(format, args...),
}
func NewErrorResponse(err error) *ErrorResponse {
return &ErrorResponse{Error: err.Error(), code: http.StatusInternalServerError}
}

func (r ErrorResponse) Write(w http.ResponseWriter) http.ResponseWriter {
func (r *ErrorResponse) Write(w http.ResponseWriter) http.ResponseWriter {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(r.code)
if err := json.NewEncoder(w).Encode(r); err != nil {
Expand Down Expand Up @@ -90,3 +82,52 @@ func WriteJSON(w http.ResponseWriter, i interface{}) {
w.Write(data)
return
}

// goImportsCode reads code from request and performs "goimports" on it
// if any error occurs, it sends error response to client and closes connection
//
// if "format" url query param is undefined or set to "false", just returns code as is
func goImportsCode(ctx context.Context, src []byte) ([]byte, bool, error) {
resp, err := goplay.GoImports(ctx, src)
if err != nil {
if err == goplay.ErrSnippetTooLarge {
return nil, false, NewHTTPError(http.StatusRequestEntityTooLarge, err)
}

return nil, false, err
}

if err = resp.HasError(); err != nil {
return nil, false, err
}

changed := resp.Body != string(src)
return []byte(resp.Body), changed, nil
}

func shouldFormatCode(r *http.Request) (bool, error) {
val := r.URL.Query().Get(formatQueryParam)
if val == "" {
return false, nil
}

boolVal, err := strconv.ParseBool(val)
if err != nil {
return false, Errorf(
http.StatusBadRequest,
"invalid %q query parameter value (expected boolean)", formatQueryParam,
)
}

return boolVal, nil
}

func getPayloadFromRequest(r *http.Request) ([]byte, error) {
src, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, Errorf(http.StatusBadGateway, "failed to read request: %s", err)
}

r.Body.Close()
return src, nil
}
Loading