Regexp matching

I want to match string that doesn’t contain “admin”

package main

import (
    "fmt"
    "regexp"
)

func main() {
    text := `admin Hello Hi.`
    reg := regexp.MustCompile(`^\b((?!admin)\w)+\b$`)
    fmt.Printf("%q\n", reg.FindAllString(text, -1))
}

Sooo, what’s wrong with strings.Contains?

I want use it with https://github.com/gorilla/mux

package main

import (
    "net/http"

    "github.com/gorilla/mux"
)

func YourHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Gorilla!\n"))
}

func main() {
    r := mux.NewRouter()
    // Routes consist of a path and a handler function.
    r.HandleFunc("/{page:\\b((?!admin)\\w)+\\b}", YourHandler)

    // Bind to a port and pass our router in
    http.ListenAndServe(":8000", r)
}

What I suppose you’re trying to do is “unless the page begins with /admin, show the user this:”. Couldn’t you do it the other way around?

Handle the case where the page begins with /admin. If mux is smart enough, it’ll only use the first handler matching that expression and so not more than one handler per request. So, if the URL doesn’t begin with /admin, it’ll use the next handler automatically.

Not expert with gorilla or anything, but I’ll try:

r.HandleFunc("/{page:\\b*admin\\b*}", AdminHandler)
r.HandleFunc("/", AllTheOtherPagesHandler)

Thanks, i have a subrouter like

  r := mux.NewRouter()
  r.HandleFunc("/{page:[a-z]+}", PageHandler)
 
  admin := r.PathPrefix("/admin").Subrouter()
  admin.HandleFunc("/posts", AdminPostHandler)
 
  http.ListenAndServe(":8000", r)

Regexp seems not support expect rule.

You won’t be able to access the admin page. You must put the admin handler BEFORE the posts handler, because otherwise it will find that the posts handler will match first, and thus ignoring the admin handler which comes straight after. This should do it:

  r := mux.NewRouter()
  admin := r.PathPrefix("/admin").Subrouter()
  admin.HandleFunc("/posts", AdminPostHandler)

  r.HandleFunc("/{page:[a-z]+}", PageHandler)

  http.ListenAndServe(":8000", r)

Thanks, that works, i only want to know if have a way to make regexp work.

What do you need it for, now?

r.HandleFunc("/{page:[a-z]+}", PageHandler)

I want it match any route only except /admin

Are we at the beginning again? You found it out yourself: Go does NOT support “does not contain” in regexps. Put a handler to /admin and then a handler for all other pages, as I’ve already told you. If you really absolutely require to check it through regex, write a handler that catches all requests, and then look if the regex matches manually, so that you can do:

// Using the bang to make it "does not match"
if !<regex matches "/admin"> {
    // things
}
1 Like

I see, thanks.

The alternative would be to write a helper function or middleware that checks if !strings.Contains(r.URL, "admin") — but this is still fragile.

I think you’re finding that—in an attempt to “shortcut” writing routes out—you’re spending more time on workarounds :wink:

Sometimes it’s best to just write them out by hand (how many can you have?), which makes it easier to debug and avoids subtle bugs (regex fails, all requests hit admin route anyway).

1 Like

You are right, thanks.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.