GoLang Tutorial - Web App 6 (Validating the title with a regular expression)
Continued from Web Application Part 5.
In this post, we'll be validate the title with a regular expression. In other words, a user can supply an arbitrary path to be read/written on the server, which is a serious security flaw in the application. So, to mitigate this, we can write a function to validate the title with a regular expression.
First, we need to add regexp to the import list:
import ( "html/template" "io/ioutil" "log" "net/http" "regexp" )
Then we can create a global variable to store our validation expression:
var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")
The function regexp.MustCompile will parse and compile the regular expression, and return a regexp.Regexp. MustCompile is distinct from Compile in that it will panic if the expression compilation fails, while Compile returns an error as a second parameter.
Now, let's write a function (getTitle) that uses the validPath expression to validate path and extract the page title:
func getTitle(w http.ResponseWriter, r *http.Request) (string, error) { m := validPath.FindStringSubmatch(r.URL.Path) if m == nil { http.NotFound(w, r) return "", errors.New("Invalid Page Title") } return m[2], nil // The title is the second subexpression. }
If the title is valid, it will be returned along with a nil error value. If the title is invalid, the function will write a "404 Not Found" error to the HTTP connection, and return an error to the handler. To create a new error, we have to import the errors package as well:
import ( "html/template" "io/ioutil" "log" "net/http" "regexp" "errors" )
Let's put a call to getTitle in each of the handlers:
func viewHandler(w http.ResponseWriter, r *http.Request) { title, err := getTitle(w, r) if err != nil { return } p, err := loadPage(title) if err != nil { http.Redirect(w, r, "/edit/"+title, http.StatusFound) return } renderTemplate(w, "view", p) } func editHandler(w http.ResponseWriter, r *http.Request) { title, err := getTitle(w, r) if err != nil { return } p, err := loadPage(title) if err != nil { p = &Page{Title: title} } renderTemplate(w, "edit", p) } func saveHandler(w http.ResponseWriter, r *http.Request) { title, err := getTitle(w, r) if err != nil { return } body := r.FormValue("body") p := &Page{Title: title, Body: []byte(body)} err = p.save() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } http.Redirect(w, r, "/view/"+title, http.StatusFound) }
Let's check our app again:
If we type "/view/test911" which is not existing, the app should redirect to the "edit" page:
If we type "/view/test-911" which has "-", it should return "404 Not Found" error to the HTTP connection, and return an error to the handler because it's an invalid title:
So, everything is working as expected.
Here is the code so far:
This file is available: wiki-app-6.go
Continues to Web Application Part 7 (Function Literals and Closures).
Go Tutorial
- GoLang Tutorial - HelloWorld
- Calling code in an external package & go.mod / go.sum files
- Workspaces
- Workspaces II
- Visual Studio Code
- Data Types and Variables
- byte and rune
- Packages
- Functions
- Arrays and Slices
- A function taking and returning a slice
- Conditionals
- Loops
- Maps
- Range
- Pointers
- Closures and Anonymous Functions
- Structs and receiver methods
- Value or Pointer Receivers
- Interfaces
- Web Application Part 0 (Introduction)
- Web Application Part 1 (Basic)
- Web Application Part 2 (Using net/http)
- Web Application Part 3 (Adding "edit" capability)
- Web Application Part 4 (Handling non-existent pages and saving pages)
- Web Application Part 5 (Error handling and template caching)
- Web Application Part 6 (Validating the title with a regular expression)
- Web Application Part 7 (Function Literals and Closures)
- Building Docker image and deploying Go application to a Kubernetes cluster (minikube)
- Serverless Framework (Serverless Application Model-SAM)
- Serverless Web API with AWS Lambda
- Arrays vs Slices with an array left rotation sample
- Variadic Functions
- Goroutines
- Channels ("<-")
- Channels ("<-") with Select
- Channels ("<-") with worker pools
- Defer
- GoLang Panic and Recover
- String Formatting
- JSON
- SQLite
- Modules 0: Using External Go Modules from GitHub
- Modules 1 (Creating a new module)
- Modules 2 (Adding Dependencies)
- AWS SDK for Go (S3 listing)
- Linked List
- Binary Search Tree (BST) Part 1 (Tree/Node structs with insert and print functions)
- Go Application Authentication I (BasicAuth, Bearer-Token-Based Authentication)
- Go Application Authentication II (JWT Authentication)
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization