Creating a custom error in golang for http responses - node.js

i wanted to create custom errors for my authentication service that i am currently working on.
Since i have to create a error for every http responses, and i am fairly new to golang i am facing difficulties.
The below code is the replica of the javascript code code that i wanted to implement here in go.
export abstract class CustomError extends Error {
abstract statusCode: number;
constructor(message: string) {
super(message);
Object.setPrototypeOf(this, CustomError.prototype);
}
abstract serializeErrors(): { message: string; field?: string }[];
}
To create extended classes based on the custom error like this
import { CustomError } from "./custom-error";
export class NotFoundError extends CustomError {
statusCode = 404;
constructor() {
super("Route not found");
Object.setPrototypeOf(this, NotFoundError.prototype);
}
serializeErrors() {
return [{ message: "Not Found" }];
}
}
so that i can be thrown or logged from the main file i.e.
const existingUser = await User.findOne({ email });
if (existingUser) {
throw new BadRequestError("Email is already in use");
}
so in simple language i wanted to create an object/model of CustomErrors that can help to create more diverse Erros like BadRequestError()
so, i need help regarding creating this one. And this is my first question here

In Go you create a custom error type simply by implementing the error interface.
The error interface is:
type error interface {
Error() string
}
[if you're completely new to Go, I suggest starting with the Tour of Go on interfaces]
For example:
type SyntaxError struct {
msg string // description of error
Offset int64 // error occurred after reading Offset bytes
}
func (e *SyntaxError) Error() string { return e.msg }
See this official Go blog post for more details.
This is for error types; if you're specifically looking for HTTP errors, those in a server are done by writing an error status to a http.ResponseWriter along with the error message you need, and you can use the helper http.Error for this. Example:
func myHandler(w http.ResponseWriter, req *http.Request) {
if (somethingIsWrong) {
http.Error(w, "the error message", http.StatusBadRequest)
}
}
The last param to http.Error is the HTTP status; check out the net/http stdlib package docs for the options you have there.
Now, to connect the two, http.Error would typically use the Error() method of your custom error as the message, and the status is really application specific.

If you want http error responses in plain text, http.Error should be your choice. But if your authentication service needs error response in specific format (JSON/XML) then you need to create custom http errors which can be serialized and written into the response.
To create custom http error responses for JSON format (for XML format modify serialization), first you need to create some types -
type ErrFields map[string]string // Error field-value pair type
type ResponseError struct {
Msg string `json:"message"` // Error message
Status int `json:"status"` // Http status code
Data ErrFields // For extra error fields e.g. reason, details, etc.
}
type ErrList []ResponseError // Multiple http errors type
Methods for ResponseError type -
// AddErrField adds a new field to the response error with given key and value
func (err *ResponseError) AddErrField(key, value string) {
if err.Data == nil {
err.Data = make(ErrFields)
}
err.Data[key] = value
}
// RemoveErrField removes existing field matching given key from response error
func (err *ResponseError) RemoveErrField(key string) {
delete(err.Data, key)
}
// MarshalJSON marshals the response error into json
func (err *ResponseError) MarshalJSON() ([]byte, error) {
// Determine json field name for error message
errType := reflect.TypeOf(*err)
msgField, ok := errType.FieldByName("Msg")
msgJsonName := "message"
if ok {
msgJsonTag := msgField.Tag.Get("json")
if msgJsonTag != "" {
msgJsonName = msgJsonTag
}
}
// Determine json field name for error status code
statusField, ok := errType.FieldByName("Status")
statusJsonName := "status"
if ok {
statusJsonTag := statusField.Tag.Get("json")
if statusJsonTag != "" {
statusJsonName = statusJsonTag
}
}
fieldMap := make(map[string]string)
fieldMap[msgJsonName] = err.Msg
fieldMap[statusJsonName] = fmt.Sprintf("%d", err.Status)
for key, value := range err.Data {
fieldMap[key] = value
}
return json.Marshal(fieldMap)
}
// SerializeJSON converts response error into serialized json string
func (resErr *ResponseError) SerializeJSON() (string, error) {
value, err := json.Marshal(resErr)
if err != nil {
return "", err
}
return string(value), nil
}
Methods for ErrList type -
// SerializeJSON converts error list into serialized json string
func (errList ErrList) SerializeJSON() (string, error) {
value, err := json.Marshal(errList)
if err != nil {
return "", err
}
return string(value), nil
}
Now you can create custom http error responses by creating different values of ResponseError type -
// Error returns a general response error
func Error(msg string, status int) ResponseError {
return ResponseError{msg, status, nil}
}
// Errors returns a error list containing given response errors
func Errors(errors ...ResponseError) ErrList {
return errors
}
// Specific HTTP error responses
func ErrorNotFound() ResponseError {
return Error("not found", http.StatusNotFound)
}
func ErrorBadRequest() ResponseError {
return Error("bad request", http.StatusBadRequest)
}
func ErrorInternalServerError() ResponseError {
return Error("internal server error", http.StatusInternalServerError)
}
func ErrorForbidden() ResponseError {
return Error("forbidden", http.StatusForbidden)
}
You can add/remove custom fields to the ResponseError values -
notFoundErr := ErrorNotFound()
notFoundErr.AddErrField("reason", "given 'id' does not exist")
notFoundErr.RemoveErrField("reason")
Since in Go there is no concept of throw, you can only return response error from a function -
func Foo() (resErr ResponseError, ok bool) {
...
if existingUser {
resErr = ErrorBadRequest()
resErr.AddErrField("reason", "Email is already in use")
return resErr, true
}
...
return ResponseError{}, false
}
To serialize response error into JSON -
resErr, ok := Foo()
if !ok {
json, err := resErr.SerializeJSON()
if err != nil {
// Handle serialization error
}
}
See the Go playground example here.

Related

Get client identity fabric-contract-api-go

There's a method in fabric-contract-api-go for getting transaction initiator's Identity
func (ctx *TransactionContext) GetClientIdentity() cid.ClientIdentity
How'd we use it to return client ID when, e.g., create is invoked in this contract https://github.com/hyperledger/fabric-contract-api-go/blob/master/tutorials/getting-started.md
// ...
// ...
// Create adds a new key with value to the world state
func (sc *SimpleContract) Create(ctx contractapi.TransactionContextInterface, key string, value string) error {
existing, err := ctx.GetStub().GetState(key)
if err != nil {
return errors.New("Unable to interact with world state")
}
if existing != nil {
return fmt.Errorf("Cannot create world state pair with key %s. Already exists", key)
}
err = ctx.GetStub().PutState(key, []byte(value))
if err != nil {
return errors.New("Unable to interact with world state")
}
return nil
}
// ...
// ...
GetClientIdentity returns you an interface of type ClientIdentity defined here
https://github.com/hyperledger/fabric-chaincode-go/blob/master/pkg/cid/interfaces.go
This shows you the functions you can then invoke to retrieve information about the transaction submitter (ie the client identity)

How to Return Nil String in Go?

I have a function which returns a string under certain circumstances, namely when the program runs in Linux or MacOS, otherwise the return value should be nil in order to omit some OS-specific checks further in code.
func test() (response string) {
if runtime.GOOS != "linux" {
return nil
} else {
/* blablabla*/
}
}
however when I try to compile this code I get an error:
test.go:10:3: cannot use nil as type string in return argument.
If I return just an empty string like return "", I cannot compare this return value with nil further in code.
So the question is how to return a correct nil string value?
If you can't use "", return a pointer of type *string; or–since this is Go–you may declare multiple return values, such as: (response string, ok bool).
Using *string: return nil pointer when you don't have a "useful" string to return. When you do, assign it to a local variable, and return its address.
func test() (response *string) {
if runtime.GOOS != "linux" {
return nil
} else {
ret := "useful"
return &ret
}
}
Using multiple return values: when you have a useful string to return, return it with ok = true, e.g.:
return "useful", true
Otherwise:
return "", false
This is how it would look like:
func test() (response string, ok bool) {
if runtime.GOOS != "linux" {
return "", false
} else {
return "useful", true
}
}
At the caller, first check the ok return value. If that's true, you may use the string value. Otherwise, consider it useless.
Also see related questions:
How do I represent an Optional String in Go?
Alternatives for obtaining and returning a pointer to string: How do I do a literal *int64 in Go?
Go has built-in support for multiple return values:
This feature is used often in idiomatic Go, for example to return both result and error values from a function.
In your case it could be like this:
func test() (response string, err error) {
if runtime.GOOS != "linux" {
return "", nil
} else {
/* blablabla*/
}
}
And then:
response, err := test()
if err != nil {
// Error handling code
return;
}
// Normal code
If you want to ignore the error, simply use _:
response, _ := test()
// Normal code
Go allows multiple return types. So use this to your advantage and return an error or any other type. Check this out for more info: http://golangtutorials.blogspot.com/2011/06/return-values-from-go-functions.html?m=1

NodeJS Error Encapsulation

I am currently trying to handle exceptions and errors in a NodeJS app which will be used for critical information. I need a clean error management !
I've been wondering if there is something similar to Java Exceptions encapsulation.
I'm explaning.
In Java you can do something like that :
try {
// something that throws Exception
} catch (Throwable t) {
throw new Exception("My message", t);
}
That allows you to decide when to log your exception and you get the whole stack trace and call path !
I would like to know if there is a way to do the same in NodeJS because logging at every step seems not to be the right way of doing things.
Thank you.
You should look at this module :
https://www.npmjs.com/package/verror
Joyent quote it on his error management best pratices : https://www.joyent.com/developers/node/design/errors
At Joyent, we use the verror module to wrap errors since it's
syntactically concise. As of this writing, it doesn't quite do all of
this yet, but it will be extended to do so.
It allow you to get details on error message. And tracking the step of the error.
And also hide details to the client with wrapped error : WError() who returns only the last error message.
I answer my own question to explain what i finaly did to have the wanted encapsulation.
I used https://www.npmjs.com/package/verror as Sachacr suggested.
Then I extended it that way :
my_error.js :
var VError = require('verror');
var _ = require('lodash');
function MyError() {
var args = [];
var httpErrorCode;
var cause;
if (arguments.length > 0) {
var lastArgumentIndex = [arguments.length];
cause = manageCause(lastArgumentIndex, arguments);
httpErrorCode = manageHttpCode(lastArgumentIndex, arguments);
for (var i = 0; i < lastArgumentIndex; i++) {
args[i] = arguments[i];
}
}
this.__proto__.__proto__.constructor.apply(this, args);
if (cause) {
if (this.stack) {
this.stack += '\n' + cause.stack;
} else {
this.stack = cause.stack;
}
}
this.httpErrorCode = httpErrorCode;
}
MyError.prototype.__proto__ = VError.prototype;
function manageCause(lastArgumentIndex, arguments) {
if (lastArgumentIndex[0] > 0
&& arguments[lastArgumentIndex[0] - 1] instanceof Error) {
lastArgumentIndex[0]--;
return arguments[lastArgumentIndex[0]];
}
}
function manageHttpCode(lastArgumentIndex, arguments) {
if (lastArgumentIndex[0] > 0
&& _.isNumber(arguments[lastArgumentIndex[0] - 1])) {
lastArgumentIndex[0]--;
return arguments[lastArgumentIndex[0]];
}
}
module.exports = MyError;
It allows me to use it easily in my code :
var MyError = require('./my_error.js');
function withErrors() {
try {
// something with errors
} catch (err) {
// This is the same pattern as VError
return new MyError("My message", err, 401);
}
}
function somethingToDo(req, res) {
var result = withErrors();
if (result instanceof MyError) {
logger.warn(result);
res.status(result.httpErrorCode).send(result.message).end();
return
}
}
That way, i hace a nice stack trace with call path and every line involved in error/exception.
Hope it will help people, cause i searched a looooong time :)
EDIT : I modified my MyError class to add HTTP Error codes and clean arguments management.
You should be able to do something like:
funtion exception(message, error) {
this.message = message;
this.stacktrace = error.stack;
}
try {
if(someData == false)
throw new exception("something went wrong!", new Error());
}
catch(ex) {
console.log(ex.message);
console.log(ex.stacktrace);
}
You can then throw your own custom exception instance containing whatever debugging info you need.
EDIT: added stack trace to exception object

Handling errors from Swift 2.0 String object functions

I'm new to Swift 2.0 programming (coming from the world of C#), and I'm simply trying to write a function to parse some data from a string and return the result. The function itself works well, but as part of the process, the string functions may throw and error if the input string is improperly formatted and I would like to prepare a catch-all error handler for the function to deal with this. Here's the code for the original function without error handling:
// Parses the numeric value of the BATT return string
private func parseBatteeryLevel(inputStr : String) -> Int {
if inputStr.hasPrefix("BATT") && inputStr.containsString("%") {
let start = inputStr.startIndex.advancedBy(5)
let end = inputStr.characters.indexOf("%")?.advancedBy(-1)
if end != nil {
return Int(inputStr.substringWithRange(start...end!))!
}else{
return 0
}
}else{
printStatus("Return Value Parse Error: \"\(inputStr)\"")
return 0
}
}
As you can see, I did implement a basic sanity check for the strings that could be inputted but it is by no means exaustive. My primary concern is what happens if is passes the checks, but causes the advanceBy() or any of the internal string functions to fail?
I did try to wrap the code in a do-catch block as shown below,
private func parseBatteeryLevel(inputStr : String) -> Int {
if inputStr.hasPrefix("BATT") && inputStr.containsString(" ") {
do {
let start = try inputStr.startIndex.advancedBy(5)
let end = try inputStr.characters.indexOf("%")?.advancedBy(-1)
if end != nil {
return try Int(inputStr.substringWithRange(start...end!))!
}else{
return 0
}
} catch let error as NSError {
printStatus(error.description)
}
}else{
printStatus("Return Value Parse Error: \"\(inputStr)\"")
return 0
}
}
but then I get warnings, next to all the lines inside the do block, marked with the try keyword saying,
No calls to throwing functions occur within 'try' expression
Then, there is another warning next to the catch keyword saying,
'catch' block is unreachable because no errors are thrown in 'do' block
This doesn't make sense because the function clearly crashes the program if an invalid string is entered. This would be painfully simple to deal with in C# but what is the proper way to handle this in Swift 2.0?
So the problem String startIndex and characters functions do not throw and exception that can be caught by the swift do try catch block. See The Swift Programming Language (Swift 2.1) - Error Handling documentation for more info.
So I rewrote the code to deal with parsing of the integer without crashing
func parseBatteeryLevel(inputStr : String) -> Int {
if inputStr.hasPrefix("BATT") && inputStr.containsString("%") {
let start = inputStr.startIndex.advancedBy(5)
let indexOfPercent = inputStr.characters.indexOf("%")
if (indexOfPercent != nil) {
let end = indexOfPercent!.advancedBy(-1)
let batteryLevel = inputStr.substringWithRange(start...end)
if let level = Int(batteryLevel) {
return level
}
}
return 0
} else {
print("Return Value Parse Error: \"\(inputStr)\"")
return 0
}
}

How to update the value of a boolean variable in swift?

I've spent the past 3 days trying to figure this out. I can easily do what I want to do in Java but as soon as I try to do it in Swift, Xcode gives me a hard time.
In this case, I am trying to retrieve a boolean object from Parse that will tell me whether the user's email has been verified. For some reason, whenever I tell to code to check to see if the object is false, checkEmail is apparently nil. Also worth noting, if I println(checkEmail) right after var checkEmail = User["emailVerified"] as Bool I get the correct boolean value (true or false).
Its looks like as soon as the code leaves the query function, the value for checkEmail is lost.
Any ideas on what I'm doing wrong?
import UIKit
class RegisterEmail: UIViewController {
var checkEmail: Bool?
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func shouldPerformSegueWithIdentifier(identifier: String!, sender: AnyObject!) -> Bool {
if identifier == "passEmail" {
var query = PFUser.query()
query.getObjectInBackgroundWithId("vFu93HatwL") {
(User: PFObject!, error: NSError!) -> Void in
if error == nil {
NSLog("%#", User)
} else {
NSLog("%#", error)
}
let checkEmail = User["emailVerified"] as Bool
println(checkEmail) //I get the correct value here
}
println(checkEmail) //The value is lost here
if (checkEmail == false) {
let alert = UIAlertView()
alert.title = "Error"
alert.message = "The email you have provided has not been verified."
alert.addButtonWithTitle("Dismiss")
alert.show()
return false
}
else {
return true
}
}
// by default, transition
return true
}
}
You're not assigning the new value to the object property, you're assigning it to a local variable. Get rid of the let keyword, which declares a new local variable, in:
let checkEmail = User["emailVerified"] as Bool

Resources