initial commits
parent
49778ecc54
commit
2f0bb9cf5e
|
@ -0,0 +1,97 @@
|
|||
package mstdn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"sourcecode.social/reiver/go-opt"
|
||||
)
|
||||
|
||||
func errorJSON(writer io.Writer, statusCode int, msg ...interface{}) {
|
||||
if nil == writer {
|
||||
return
|
||||
}
|
||||
|
||||
// short error message.
|
||||
var short string
|
||||
{
|
||||
var shortErrorMessage opt.Optional[string]
|
||||
|
||||
shortErrorMessage.WhenNothing(func(){
|
||||
if 1 <= len(msg) {
|
||||
shortErrorMessage = opt.Something(fmt.Sprint(msg[0]))
|
||||
}
|
||||
})
|
||||
shortErrorMessage.WhenNothing(func(){
|
||||
shortErrorMessage = opt.Something(http.StatusText(statusCode))
|
||||
})
|
||||
|
||||
shortErrorMessage.WhenSomething(func(value string){
|
||||
short = value
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
var long opt.Optional[string]
|
||||
{
|
||||
if 2 <= len(msg) {
|
||||
long = opt.Something(fmt.Sprint(msg[1:]...))
|
||||
}
|
||||
}
|
||||
|
||||
var array [512]byte
|
||||
var buffer []byte = array[:0]
|
||||
{
|
||||
|
||||
buffer = append(buffer, "{"...)
|
||||
buffer = append(buffer, `"error":`...)
|
||||
{
|
||||
// This should never return an error since we are passing a string.
|
||||
marshaled, _ := json.Marshal(short)
|
||||
|
||||
buffer = append(buffer, marshaled...)
|
||||
}
|
||||
|
||||
long.WhenSomething(func(value string){
|
||||
buffer = append(buffer, `,"error_description":`...)
|
||||
|
||||
// This should never return an error since we are passing a string.
|
||||
marshaled, _ := json.Marshal(value)
|
||||
|
||||
buffer = append(buffer, marshaled...)
|
||||
})
|
||||
buffer = append(buffer, "}"...)
|
||||
}
|
||||
|
||||
writer.Write(buffer)
|
||||
}
|
||||
|
||||
// Error responds to the request with the specified error message and HTTP code.
|
||||
// The response will be in JSON (application/json; charset=utf-8).
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var statusCode int = http.StatusUnauthorized
|
||||
// var shortErrorMessage = http.StatusText(http.StatusUnauthorized)
|
||||
// var longErrorMessage = "Access Denied!!! — you can keep on knocking but you can't come in"
|
||||
//
|
||||
// mstdn.Error(resp, statusCode, shortErrorMessage, longErrorMessage)
|
||||
//
|
||||
// Responds with:
|
||||
//
|
||||
// {
|
||||
// "error":"Unauthorized",
|
||||
// "error_description":"Access Defined!!!! — you can keep on knocking but you can't come in"
|
||||
// }
|
||||
func Error(resp http.ResponseWriter, statusCode int, msg ...interface{}) {
|
||||
if nil == resp {
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeader(statusCode)
|
||||
resp.Header().Add("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
errorJSON(resp, statusCode, msg...)
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package mstdn
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"strings"
|
||||
)
|
||||
|
||||
func TestErrorJSON(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
StatusCode int
|
||||
Message []interface{}
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
StatusCode: 400,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Bad Request"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 401,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Unauthorized"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 403,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Forbidden"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 404,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Not Found"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 422,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Unprocessable Entity"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 429,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Too Many Requests"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 500,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Internal Server Error"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 503,
|
||||
Message: []interface{}{},
|
||||
Expected: `{"error":"Service Unavailable"}`,
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
StatusCode: 400,
|
||||
Message: []interface{}{"very bad request"},
|
||||
Expected: `{"error":"very bad request"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 401,
|
||||
Message: []interface{}{"get out of here"},
|
||||
Expected: `{"error":"get out of here"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 403,
|
||||
Message: []interface{}{"no!!!!"},
|
||||
Expected: `{"error":"no!!!!"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 404,
|
||||
Message: []interface{}{"huh?"},
|
||||
Expected: `{"error":"huh?"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 422,
|
||||
Message: []interface{}{"WTF?"},
|
||||
Expected: `{"error":"WTF?"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 429,
|
||||
Message: []interface{}{"f-off"},
|
||||
Expected: `{"error":"f-off"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 500,
|
||||
Message: []interface{}{"crap!"},
|
||||
Expected: `{"error":"crap!"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 503,
|
||||
Message: []interface{}{"nope"},
|
||||
Expected: `{"error":"nope"}`,
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
StatusCode: 400,
|
||||
Message: []interface{}{"very bad request", "you have been naughty"},
|
||||
Expected: `{"error":"very bad request","error_description":"you have been naughty"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 401,
|
||||
Message: []interface{}{"get out of here", "access denied!!! — you can keep on knocking but you can't come in"},
|
||||
Expected: `{"error":"get out of here","error_description":"access denied!!! — you can keep on knocking but you can't come in"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 403,
|
||||
Message: []interface{}{"no!!!!", "go away"},
|
||||
Expected: `{"error":"no!!!!","error_description":"go away"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 404,
|
||||
Message: []interface{}{"huh?", "what are you talking about"},
|
||||
Expected: `{"error":"huh?","error_description":"what are you talking about"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 422,
|
||||
Message: []interface{}{"WTF?", "i don't understand the words coming out of your mouth"},
|
||||
Expected: `{"error":"WTF?","error_description":"i don't understand the words coming out of your mouth"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 429,
|
||||
Message: []interface{}{"f-off", "slow it down, back it up"},
|
||||
Expected: `{"error":"f-off","error_description":"slow it down, back it up"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 500,
|
||||
Message: []interface{}{"crap!", "i f-ed up"},
|
||||
Expected: `{"error":"crap!","error_description":"i f-ed up"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 503,
|
||||
Message: []interface{}{"nope", "it not workie"},
|
||||
Expected: `{"error":"nope","error_description":"it not workie"}`,
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
StatusCode: 400,
|
||||
Message: []interface{}{"very bad request", "you have been naughty", " :-)"},
|
||||
Expected: `{"error":"very bad request","error_description":"you have been naughty :-)"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 401,
|
||||
Message: []interface{}{"get out of here", "access denied!!! — you can keep on knocking but you can't come in", "."},
|
||||
Expected: `{"error":"get out of here","error_description":"access denied!!! — you can keep on knocking but you can't come in."}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 403,
|
||||
Message: []interface{}{"no!!!!", "go away", "!"},
|
||||
Expected: `{"error":"no!!!!","error_description":"go away!"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 404,
|
||||
Message: []interface{}{"huh?", "what are you talking about", "?"},
|
||||
Expected: `{"error":"huh?","error_description":"what are you talking about?"}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 422,
|
||||
Message: []interface{}{"WTF?", "i don't understand the words coming out of your mouth", "."},
|
||||
Expected: `{"error":"WTF?","error_description":"i don't understand the words coming out of your mouth."}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 429,
|
||||
Message: []interface{}{"f-off", "slow it down, back it up", "."},
|
||||
Expected: `{"error":"f-off","error_description":"slow it down, back it up."}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 500,
|
||||
Message: []interface{}{"crap!", "i f-ed up", " :-("},
|
||||
Expected: `{"error":"crap!","error_description":"i f-ed up :-("}`,
|
||||
},
|
||||
{
|
||||
StatusCode: 503,
|
||||
Message: []interface{}{"nope", "it not workie", "."},
|
||||
Expected: `{"error":"nope","error_description":"it not workie."}`,
|
||||
},
|
||||
}
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
var actualBuffer strings.Builder
|
||||
|
||||
errorJSON(&actualBuffer, test.StatusCode, test.Message...)
|
||||
|
||||
actual := actualBuffer.String()
|
||||
expected := test.Expected
|
||||
|
||||
if expected != actual {
|
||||
t.Errorf("For test #%d, the actual value is not what was expected.", testNumber)
|
||||
t.Logf("EXPECTED:\n%s", expected)
|
||||
t.Logf("ACTUAL:\n%s", actual)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue