labstack / echo

High performance, minimalist Go web framework

Home Page:https://echo.labstack.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

QueryParams seem to override formValues

sarthakagrawal927 opened this issue · comments

Issue Description

I am a bit of a beginner in go. Due to lack of good validation libraries I decided to write my own custom validator, while testing I came to realise that formValue was being overridden by queryParam (or if queryParam of same key exists it ignores formValue).

Checklist

  • [+] Dependencies installed
  • [+] No typos
  • [-] Searched existing issues and docs (couldn't find anything relevant)

Expected behaviour

When accessing formValue we should just get formValue & not queryParam

Actual behaviour

c.FormValue is taking values from queryParams and also overriding any values present in formValue. I am using this curl

curl --location 'http://localhost:1323/api/consumable?smallest_unit_label=queryParam&title=dumb&desc=this%20can%20be%20goood&habit_id=1&num_total_unit=2&time_per_unit=3&num_remaining_unit=0' \ --header 'Cookie: lang=en-US' \ --form 'smallest_unit_label="form"' \ --form 'title="dumb2"'

Accessing for formValue for title is giving "dumb" instead of "dumb2"

Steps to reproduce

Running this piece of code in simple server:

fmt.Println(c.FormValue("title"), c.QueryParam("title"), c.FormValue("habit_id"), c.FormValue("smallest_unit_label"), c.QueryParam("smallest_unit_label"))
is resulting in "dumb dumb 1 queryParam queryParam" for the above curl.

Version/commit

Go: 1.21.6
Echo: github.com/labstack/echo/v4 v4.11.2

Is this expected behaviour?

This is how form parsing works with Go standard library. Echo uses Standard library implementation under the hood.

This is curl with verbose

> POST /api/consumable?smallest_unit_label=queryParam&title=dumb&desc=this%20can%20be%20goood&habit_id=1&num_total_unit=2&time_per_unit=3&num_remaining_unit=0 HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/8.2.1
> Accept: */*
> Cookie: lang=en-US
> Content-Length: 257
> Content-Type: multipart/form-data; boundary=------------------------863b3c936c4390e3

You are doing POST method with content type multipart/form-data and this will processed by this Standard library method https://github.com/golang/go/blob/f719d5cffdb8298eff7a5ef533fe95290e8c869c/src/net/http/request.go#L1281

That metho document comment says that it uses URL values also.

// ParseForm populates r.Form and r.PostForm.
//
// For all requests, ParseForm parses the raw query from the URL and updates
// r.Form.
//
// For POST, PUT, and PATCH requests, it also reads the request body, parses it
// as a form and puts the results into both r.PostForm and r.Form. Request body
// parameters take precedence over URL query string values in r.Form.

You can access only posted form data by c.Request().PostForm.Get("smallest_unit_label")

Interesting, thank you for your response!

Its always nice to see the thought process behind a particular feature.