Skip to content

Commit

Permalink
- Fix errors
Browse files Browse the repository at this point in the history
- Fix response interface
- Fix base response struct methods
- Fix CORS for empty response headers (fix response struct)
- Up version
  • Loading branch information
legion-zver committed Jul 1, 2018
1 parent 03f94a8 commit 8f7f6d8
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 32 deletions.
6 changes: 5 additions & 1 deletion base-serializers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import (
"net/url"
)

var (
ErrSerializeOperationsDisabled = errors.New("serialize operations disabled")
)

// Base JSON serializer.
type JsonSerializer struct {
Ch string // Charset for generate Content-Type header.
Expand Down Expand Up @@ -129,7 +133,7 @@ func (s FormSerializer) DefaultContentType(withCharset bool) string {

func (s FormSerializer) Serialize(v interface{}) ([]byte, error) {
if s.OnlyDeserialize {
return nil, errors.New("Serialize operations disabled")
return nil, ErrSerializeOperationsDisabled
}
if input, ok := v.(ISerializeInput); ok {
v = input.Data()
Expand Down
4 changes: 4 additions & 0 deletions components/cors/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"strings"
"time"

"fmt"

"github.com/itrabbit/just"
)

Expand Down Expand Up @@ -94,6 +96,8 @@ func Middleware(options Options) just.HandlerFunc {
if len(options.ExposeHeaders) > 0 {
headers["Access-Control-Expose-Headers"] = strings.Join(options.ExposeHeaders, ",")
}
} else {
fmt.Println("[WARNING][CORS] Can't change response for", c.Request.URL.String())
}
}
return res
Expand Down
18 changes: 13 additions & 5 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import (
"time"
)

// Errors
var (
ErrEmptyRequest = errors.New("empty request")
ErrEmptyRequestBody = errors.New("empty request body")
ErrNotFoundSerializer = errors.New("not find serializer for content type in your request")
ErrNotFoundUrlSerializer = errors.New("not find serializer for url query (application/x-www-form-urlencoded)")
)

// Request Context struct.
type Context struct {
// Private props.
Expand Down Expand Up @@ -127,21 +135,21 @@ func (c *Context) S(names ...string) ISerializer {
// DeSerializing body or query to object
func (c *Context) Bind(ptr interface{}) error {
if c.Request == nil {
return errors.New("Empty request")
return ErrEmptyRequest
}
if (c.Request.Method == "GET" || c.Request.Method == "DELETE") && c.Request.URL != nil {
s := c.app.SerializerManager().Serializer("application/x-www-form-urlencoded", true)
if s == nil {
return errors.New("Not find Serializer for url query (application/x-www-form-urlencoded)")
return ErrNotFoundUrlSerializer
}
return s.Deserialize([]byte(c.Request.URL.RawQuery), ptr)
}
if c.Request.Body == nil {
return errors.New("Empty request body")
return ErrEmptyRequestBody
}
s := c.app.SerializerManager().Serializer(c.ContentType(), true)
if s == nil {
return errors.New("Not find Serializer for " + c.ContentType())
return ErrNotFoundSerializer
}
b, err := ioutil.ReadAll(c.Request.Body)
defer c.ResetBodyReaderPosition()
Expand Down Expand Up @@ -684,7 +692,7 @@ func (c *Context) UserAgent() string {

// Get the Content-Type header of the request.
func (c *Context) ContentType() string {
contentType := c.MustRequestHeader("Content-Type")
contentType := c.MustRequestHeader(ContentTypeHeaderKey)
for i, ch := range contentType {
if ch == ' ' || ch == ';' {
contentType = strings.TrimSpace(contentType[:i])
Expand Down
12 changes: 9 additions & 3 deletions form-mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ import (
"time"
)

var (
ErrUnknownType = errors.New("unknown type")
ErrBlankTimeFormat = errors.New("blank time format")
ErrOnlyStructUrlEncode = errors.New("array and slice by root element not supported, only structure")
)

func marshalUrlValues(ptr interface{}) ([]byte, error) {
t, v := reflect.TypeOf(ptr).Elem(), reflect.ValueOf(ptr).Elem()
if t.Kind() == reflect.Array || t.Kind() == reflect.Slice {
return nil, errors.New("Array and slice by root element not supported, only structure!")
return nil, ErrOnlyStructUrlEncode
}
values := make(url.Values)
for i := 0; i < t.NumField(); i++ {
Expand Down Expand Up @@ -147,7 +153,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
case reflect.String:
structField.SetString(val)
default:
return errors.New("Unknown type")
return ErrUnknownType
}
return nil
}
Expand Down Expand Up @@ -199,7 +205,7 @@ func setFloatField(val string, bitSize int, field reflect.Value) error {
func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
timeFormat := structField.Tag.Get("time_format")
if timeFormat == "" {
return errors.New("Blank time format")
return ErrBlankTimeFormat
}
if val == "" {
value.Set(reflect.ValueOf(time.Time{}))
Expand Down
21 changes: 13 additions & 8 deletions just.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

const (
Version = "v0.1.17"
Version = "v0.1.18"
DebugEnvName = "JUST_DEBUG_MODE"
)

Expand All @@ -24,6 +24,12 @@ var (
debugMode = true
)

// Errors
var (
ErrInvalidContext = errors.New("invalid context")
ErrRecoverInvalidResponse = errors.New("invalid response, recover panic")
)

// JUST Application interface.
type IApplication interface {
IRouter
Expand Down Expand Up @@ -119,7 +125,7 @@ func (app *application) checkMethodForHaveBody(method string) bool {
func (app *application) handleHttpRequest(w http.ResponseWriter, c *Context) {
if !c.IsValid() {
if app.profiler != nil {
app.profiler.Warning(errors.New("Invalid context"))
app.profiler.Warning(ErrInvalidContext)
}
return
}
Expand Down Expand Up @@ -150,7 +156,7 @@ func (app *application) handleHttpRequest(w http.ResponseWriter, c *Context) {

http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
if app.profiler != nil {
app.profiler.Error(errors.New("invalid response, recover panic"))
app.profiler.Error(ErrRecoverInvalidResponse)
}
}
}()
Expand Down Expand Up @@ -179,14 +185,13 @@ func (app *application) handleHttpRequest(w http.ResponseWriter, c *Context) {
if streamFunc, ok := response.GetStreamHandler(); ok {
streamFunc(w, c.Request)
} else {
if headers := response.GetHeaders(); len(headers) > 0 {
if response.HasHeaders() {
// Обработка заголовков
for key, value := range headers {
if key == "_StrongRedirect" {
for key, value := range response.GetHeaders() {
if key == StrongRedirectHeaderKey {
http.Redirect(w, c.Request, value, response.GetStatus())
return
}
if key == "_FilePath" {
} else if key == ServeFileHeaderKey {
http.ServeFile(w, c.Request, value)
return
}
Expand Down
52 changes: 42 additions & 10 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,19 @@ import (
"net/http"
)

const (
ContentTypeHeaderKey = "Content-Type"
StrongRedirectHeaderKey = "__StrongRedirect"
ServeFileHeaderKey = "__ServeFilePath"
)

// Response interface.
type IResponse interface {
// Checkers
HasData() bool
HasHeaders() bool
HasStreamHandler() bool
// Getters
GetData() []byte
GetStatus() int
GetHeaders() map[string]string
Expand All @@ -22,22 +33,43 @@ type Response struct {
Stream http.HandlerFunc // Stream method, to support standard HTTP package, as well as to work with WS.
}

func (r *Response) GetStreamHandler() (http.HandlerFunc, bool) {
if r.Stream != nil && (r.Bytes == nil || len(r.Bytes) < 1) {
func (r Response) HasStreamHandler() bool {
return r.Stream != nil
}

func (r Response) GetStreamHandler() (http.HandlerFunc, bool) {
if r.Stream != nil {
return r.Stream, true
}
return nil, false
}

func (r *Response) GetStatus() int {
func (r Response) HasData() bool {
if r.Bytes == nil {
return false
}
return len(r.Bytes) > 0
}

func (r Response) GetStatus() int {
return r.Status
}

func (r *Response) GetData() []byte {
func (r Response) GetData() []byte {
return r.Bytes
}

func (r Response) HasHeaders() bool {
if r.Headers == nil {
return false
}
return len(r.Headers) > 0
}

func (r *Response) GetHeaders() map[string]string {
if r.Headers == nil {
r.Headers = make(map[string]string)
}
return r.Headers
}

Expand All @@ -53,13 +85,13 @@ func JsonResponse(status int, v interface{}) IResponse {
return &Response{
Bytes: []byte(err.Error()),
Status: 500,
Headers: map[string]string{"Content-Type": "plain/text; charset=utf-8"},
Headers: map[string]string{ContentTypeHeaderKey: "plain/text; charset=utf-8"},
}
}
return &Response{
Bytes: b,
Status: status,
Headers: map[string]string{"Content-Type": "application/json; charset=utf-8"},
Headers: map[string]string{ContentTypeHeaderKey: "application/json; charset=utf-8"},
}
}

Expand All @@ -68,7 +100,7 @@ func RedirectResponse(status int, location string) IResponse {
if (status < 300 || status > 308) && status != 201 {
status = 301
}
return &Response{Bytes: nil, Status: status, Headers: map[string]string{"_StrongRedirect": location}}
return &Response{Bytes: nil, Status: status, Headers: map[string]string{StrongRedirectHeaderKey: location}}
}

// Create a XML response.
Expand All @@ -78,17 +110,17 @@ func XmlResponse(status int, v interface{}) IResponse {
return &Response{
Bytes: []byte(err.Error()),
Status: 500,
Headers: map[string]string{"Content-Type": "plain/text; charset=utf-8"},
Headers: map[string]string{ContentTypeHeaderKey: "plain/text; charset=utf-8"},
}
}
return &Response{
Bytes: b,
Status: status,
Headers: map[string]string{"Content-Type": "application/xml; charset=utf-8"},
Headers: map[string]string{ContentTypeHeaderKey: "application/xml; charset=utf-8"},
}
}

// Create a response in the form of a local file.
func FileResponse(filePath string) IResponse {
return &Response{Bytes: nil, Status: -1, Headers: map[string]string{"_FilePath": filePath}}
return &Response{Bytes: nil, Status: -1, Headers: map[string]string{ServeFileHeaderKey: filePath}}
}
9 changes: 7 additions & 2 deletions templating.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import (
"sync"
)

// Errors
var (
ErrEmptyTemplates = errors.New("have hot templates")
)

// Interface for rendering templates.
type IRenderer interface {
DefaultContentType(withCharset bool) string
Expand Down Expand Up @@ -134,7 +139,7 @@ func (r *HTMLRenderer) RemoveFunc(name string) IRenderer {
// Render HTML to bytes.
func (r *HTMLRenderer) Render(name string, data interface{}) ([]byte, error) {
if r.template == nil {
return nil, errors.New("Have hot templates")
return nil, ErrEmptyTemplates
}
var buffer bytes.Buffer
if err := r.template.ExecuteTemplate(&buffer, name, data); err != nil {
Expand All @@ -150,7 +155,7 @@ func (r *HTMLRenderer) Response(status int, name string, data interface{}) IResp
Status: status,
Bytes: b,
Headers: map[string]string{
"Content-Type": r.DefaultContentType(true),
ContentTypeHeaderKey: r.DefaultContentType(true),
},
}
}
Expand Down
10 changes: 8 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import (
"strings"
)

// Errors
var (
ErrEmptyReader = errors.New("reader is empty")
ErrUnsupportedReader = errors.New("reader is not supported")
)

func topSeekReader(reader io.Reader, nopDetect bool) (int64, error) {
if reader != nil {
if nopDetect {
Expand All @@ -29,9 +35,9 @@ func topSeekReader(reader io.Reader, nopDetect bool) (int64, error) {
} else if f, ok := reader.(*os.File); ok {
return f.Seek(0, io.SeekStart)
}
return -1, errors.New("Reader is not supported")
return -1, ErrUnsupportedReader
}
return -1, errors.New("Reader is empty")
return -1, ErrEmptyReader
}

func joinPaths(a string, b string) string {
Expand Down
2 changes: 1 addition & 1 deletion validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func Validation(obj interface{}) []error {
case reflect.String:
err = validationString(val.Field(i).String(), instruction)
default:
err = errors.New("Unsupported validator")
err = errors.New("unsupported validator")
}
if err != nil {
if result == nil {
Expand Down

0 comments on commit 8f7f6d8

Please sign in to comment.