4

I'm trying to rewrite a small node-api in golang and there I found that the internal error doesn't stop the processing of the requests. Is there a nice way to end the processing?

I've tried different things like making a error-object and using panic(err) to exit the processing but I think there are better ways.

I expected a function which stops the processing of the request and throws an 500-error and maybe logs a thing or two.

The code-sample is like this:

package main

import (
    "fmt"
    "net/http"
    "strings"
)

func main() {
    http.HandleFunc("/ping/", ping)
    err := http.ListenAndServe(":8080", nil)
    checkErr(err)
}

func ping(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("pong\n"))
    urlPath := req.URL.Path
    rest := strings.TrimPrefix(urlPath, "/ping/")
    testRest(w, rest)
}

func testRest(w http.ResponseWriter, rest string) {
    if rest == "abc" {
        http.Error(w, "The go-routine should stop here", 500)
    }
    fmt.Print("This shouldn't be printed")
}

func checkErr(err error) {
    if err != nil {
        panic(err)
    }
}

And I call it like that:

curl --url http://127.0.0.1:8080/ping/abc
4
  • 4
    please share the code you have written. Commented Sep 3, 2019 at 17:57
  • 1
    I'm with @dassum, please share your code, because it is unclear what you mean by "internal error" and it is unclear what you've tried so far to "exit the processing". Commented Sep 3, 2019 at 18:00
  • 3
    Hard to say without seeing the code but it seems very likely it's as simple as "when you get an error, write a 500 response to the client and return from your handler". Commented Sep 3, 2019 at 18:30
  • I included the code in my question and from my understanding of the comment from @Adrian he is right. Commented Sep 5, 2019 at 7:17

2 Answers 2

10

There is no trick to it. When you want your handler function to stop doing things, just return from the function:

func testRest(w http.ResponseWriter, rest string) {
    if rest == "abc" {
        http.Error(w, "The go-routine should stop here", 500)
        return
    }
    fmt.Print("This shouldn't be printed")
}

If you want to log something, log something:

func testRest(w http.ResponseWriter, rest string) {
    if rest == "abc" {
        http.Error(w, "The go-routine should stop here", 500)
        log.Println("something bad happened")
        return
    }
    fmt.Print("This shouldn't be printed")
}

That's all there is to it. When you say "internal error doesn't stop the processing of the requests" it seems maybe you're thinking there's a lot more magic happening, but in Go there's very little magic. http.Error writes an error response back to the client. That's all. It has not way to "stop" anything; it just writes a status code and body to the client connection and then returns. After it returns, you have the opportunity to do more things in the calling code, but if you just want your function to return, then just return. Returning from the handler is what "stops processing the request" - your code is what's processing the request, you're in complete control.

Sign up to request clarification or add additional context in comments.

Comments

-2

I'd use cancellation by using the context library native in Go.

an example of how you could active that: https://play.golang.org/p/qF7aQ1DP3vM

Here a nice artice about the topic: https://medium.com/the-software-firehose/canceling-requests-in-go-using-context-b4b28a118da8

Edit

It's important to keep in mind that this would be a solution for client requests only. If you want to cancel requests from server a different approach might be necessary.

7 Comments

This is a nice answer when one wants to cancel client requests, however, since Luca R is implementing an api and they want to "throw" a 500 error, I would assume they are talking about server requests... although we can't be sure since they haven't provided no code...
Would either acting as a client or acting as a server both use a Context value to include either a timeout or manual cancelation ability or both? (e.g.: acting as a client you would give a Context with timeout/cancel to the client lib, while acting as a server you would give a Context with timeout/cancel to the DB library or use it internally to look for cancellation?)
@Freezerburn context is a powerful resource for either client and server operations because it works nicely in the goroutine ecosystem and as a channel value. So I would use it for both. About use manual cancellation or timeout I think I depends on your needs, but It's always nice to set some sort of timeout and the context lib is great for that. Also, I would never use it to cancel the DB lib before cleaning the connection.
@NicolasAugustoSassi sql.DB.BeginTx(context.Context, *TxOptions) is available for preventing any given set of queries from taking more than some given timeout if you configure a context with one. So if a server is handling a request and it cannot take more than 200 milliseconds to respond, there's a way to stop the DB driver from processing beyond that and give you the opportunity to respond with the correct error.
@Freezerburn didn't know about this sql lib resource. Thanks for that!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.