gophi/error.go
kim (grufwub) cb81cbcc72 fix errors to send with lastline
Signed-off-by: kim (grufwub) <grufwub@gmail.com>
2020-04-24 12:28:38 +01:00

176 lines
5.1 KiB
Go

package main
import (
"fmt"
)
/* Simple error code type defs */
type ErrorCode int
type ErrorResponseCode int
const (
/* Filesystem */
PathEnumerationErr ErrorCode = iota
IllegalPathErr ErrorCode = iota
FileStatErr ErrorCode = iota
FileOpenErr ErrorCode = iota
FileReadErr ErrorCode = iota
FileTypeErr ErrorCode = iota
DirListErr ErrorCode = iota
/* Sockets */
SocketWriteErr ErrorCode = iota
SocketWriteCountErr ErrorCode = iota
/* Parsing */
InvalidRequestErr ErrorCode = iota
EmptyItemTypeErr ErrorCode = iota
EntityPortParseErr ErrorCode = iota
InvalidGophermapErr ErrorCode = iota
/* Error Response Codes */
ErrorResponse200 ErrorResponseCode = iota
ErrorResponse400 ErrorResponseCode = iota
ErrorResponse401 ErrorResponseCode = iota
ErrorResponse403 ErrorResponseCode = iota
ErrorResponse404 ErrorResponseCode = iota
ErrorResponse408 ErrorResponseCode = iota
ErrorResponse410 ErrorResponseCode = iota
ErrorResponse500 ErrorResponseCode = iota
ErrorResponse501 ErrorResponseCode = iota
ErrorResponse503 ErrorResponseCode = iota
NoResponse ErrorResponseCode = iota
)
/* Simple GophorError data structure to wrap another error */
type GophorError struct {
Code ErrorCode
Err error
}
/* Convert error code to string */
func (e *GophorError) Error() string {
var str string
switch e.Code {
case PathEnumerationErr:
str = "path enumeration fail"
case IllegalPathErr:
str = "illegal path requested"
case FileStatErr:
str = "file stat fail"
case FileOpenErr:
str = "file open fail"
case FileReadErr:
str = "file read fail"
case FileTypeErr:
str = "invalid file type"
case DirListErr:
str = "directory read fail"
case SocketWriteErr:
str = "socket write fail"
case SocketWriteCountErr:
str = "socket write count mismatch"
case InvalidRequestErr:
str = "invalid request data"
case EmptyItemTypeErr:
str = "line string provides no dir entity type"
case EntityPortParseErr:
str = "parsing dir entity port"
case InvalidGophermapErr:
str = "invalid gophermap"
default:
str = "Unknown"
}
if e.Err != nil {
return fmt.Sprintf("%s (%s)", str, e.Err.Error())
} else {
return fmt.Sprintf("%s", str)
}
}
/* Convert a gophor error code to appropriate error response code */
func gophorErrorToResponseCode(code ErrorCode) ErrorResponseCode {
switch code {
case PathEnumerationErr:
return ErrorResponse400
case IllegalPathErr:
return ErrorResponse403
case FileStatErr:
return ErrorResponse404
case FileOpenErr:
return ErrorResponse404
case FileReadErr:
return ErrorResponse404
case FileTypeErr:
/* If wrong file type, just assume file not there */
return ErrorResponse404
case DirListErr:
return ErrorResponse404
/* These are errors _while_ sending, no point trying to send error */
case SocketWriteErr:
return NoResponse
case SocketWriteCountErr:
return NoResponse
case InvalidRequestErr:
return ErrorResponse400
case EmptyItemTypeErr:
return ErrorResponse500
case EntityPortParseErr:
return ErrorResponse500
case InvalidGophermapErr:
return ErrorResponse500
default:
return ErrorResponse503
}
}
/* Generates gopher protocol compatible error response from our code */
func generateGopherErrorResponseFromCode(code ErrorCode) []byte {
responseCode := gophorErrorToResponseCode(code)
if responseCode == NoResponse {
return nil
}
return generateGopherErrorResponse(responseCode)
}
/* Generates gopher protocol compatible error response for response code */
func generateGopherErrorResponse(code ErrorResponseCode) []byte {
return buildError(code.String())
}
/* Error response code to string */
func (e ErrorResponseCode) String() string {
switch e {
case ErrorResponse200:
return "200 OK"
case ErrorResponse400:
return "400 Bad Request"
case ErrorResponse401:
return "401 Unauthorised"
case ErrorResponse403:
return "403 Forbidden"
case ErrorResponse404:
return "404 Not Found"
case ErrorResponse408:
return "408 Request Time-out"
case ErrorResponse410:
return "410 Gone"
case ErrorResponse500:
return "500 Internal Server Error"
case ErrorResponse501:
return "501 Not Implemented"
case ErrorResponse503:
return "503 Service Unavailable"
default:
/* Should not have reached here */
Config.LogSystemFatal("Unhandled ErrorResponseCode type\n")
return ""
}
}