fasthttp icon indicating copy to clipboard operation
fasthttp copied to clipboard

Peek Headers with the same name

Open nsagnett opened this issue 9 years ago • 17 comments

Hi !

It's possible to get multiple headers with the same name without parsing all headers in requestHeader struct (without using visitAll function) ?

nsagnett avatar Oct 04 '16 12:10 nsagnett

ctx.Request.Header.Peek("X-Your-Some-Header")

SshPwd avatar Oct 07 '16 14:10 SshPwd

It returns the first header with "X-Your-Some-Header" name. I would like same method returns all headers named "X-Your-Some-Header"

nsagnett avatar Oct 07 '16 15:10 nsagnett

@nsagnett What do you mean, you have multiple headers with the same key?

ghost avatar Oct 07 '16 15:10 ghost

It's possible ! It's allowed by RFC

nsagnett avatar Oct 07 '16 15:10 nsagnett

Can you show example your a request with multiple headers?

SshPwd avatar Oct 07 '16 15:10 SshPwd

curl -v -H "X-Your-Some-Header: foo" -H "X-Your-Some-Header: bar" localhost:8080, you can see two headers with the same key

nsagnett avatar Oct 07 '16 15:10 nsagnett

Could you show reference to the rfc part please?

SshPwd avatar Oct 07 '16 18:10 SshPwd

https://tools.ietf.org/html/rfc3864 (2.2.1)

nsagnett avatar Oct 07 '16 18:10 nsagnett

I found https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 tnx

SshPwd avatar Oct 07 '16 18:10 SshPwd

Yes, multiple values are allowed, multiple keys are not possible, I though you meant multiple keys at my first reading, but I misunderstood, sorry. Practical you have right then, if fasthttp doesn't supports multiple headers values yet this is a problem but you can fix it with a PR, don't be afraid, we are here!

ghost avatar Oct 09 '16 01:10 ghost

@kataras "Yes, multiple values are allowed, multiple keys are not possible"

Actually, the HTTP RFC does state that multiple (duplicated) keys MAY exist in an HTTP header. They very carefully explain that proxies are not allowed to change the order of duplicates as the value order may be significant:

Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]. It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma. The order in which header fields with the same field-name are received is therefore significant to the interpretation of the combined field value, and thus a proxy MUST NOT change the order of these field values when a message is forwarded.

AlskiOnTheWeb avatar Apr 12 '17 12:04 AlskiOnTheWeb

A good library with the bad document, I even don't know how to send a customed HTTP GET request.

aiddroid avatar Jul 03 '19 05:07 aiddroid

@aiddroid Using the Request structure :) Just like this

package main

import (
	"log"

	"github.com/valyala/fasthttp"
)

func main() {
	req := fasthttp.AcquireRequest()
	res := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseRequest(req)
	defer fasthttp.ReleaseResponse(res)

	req.Header.SetMethod("GET")
	req.SetRequestURI("https://borja.es")
	req.Header.Add("X-Custom-Header", "Test")

	if err := fasthttp.Do(req,res); err != nil {
		log.Fatalln(err)
	}

	log.Printf("Response body length: %d\n", len(res.Body()))
}

dgrr avatar Jul 03 '19 08:07 dgrr

@dgrr Thanks, Add this demo to the README file may be helpful.

aiddroid avatar Jul 03 '19 09:07 aiddroid

It has been discussed previously I believe, with the suggestion to implement PeekAll that returns a slice.

For context, go stdlib merges headers since per HTTP spec K: v1\r\nK: v2 is identical to K: v1; v2. This of course impacts performance.

illotum avatar Jul 03 '19 22:07 illotum

Hi all, what is the current status of this issue?

Currently, we only able to access our duplicate key headers as below:


reqHeaders := make(map[string][]string)
req.Header.VisitAll(func(k, v []byte) {
	key := *(*string)(unsafe.Pointer(&k))
	val := *(*string)(unsafe.Pointer(&v))

	reqHeaders[key] = append(reqHeaders[key], val)
})

mstrYoda avatar Aug 22 '22 12:08 mstrYoda

I'm ok with a pull request to add methods like func (h *RequestHeader) PeekAll(key string) [][]byte.

erikdubbelboer avatar Aug 22 '22 12:08 erikdubbelboer