IBM / fp-go

functional programming library for golang
Apache License 2.0
1.63k stars 47 forks source link

http/request header issue #32

Closed thasyia closed 1 year ago

thasyia commented 1 year ago

First of all, ty for your articles and hard work on the lib - it's awesome.

I'm struggling to get my head around "how to change the request header" using http/request funcs. Normally I would do:

type headerFunc func(*http.Request) *http.Request

var (
    headers = map[string]headerFunc{
        "text": contentTypeText,
})

func contentTypeText(req *http.Request) *http.Request{
    req.Header.Set("Content-Type", "text/html")
return req
}

func MakeHeaderWithMap (req *http.Request, headerText string) *http.Request{
   if setHeader, ok := headers[headerText]; ok{
      return setHeader(req)}
  panic("header not supported")
}

In your sample ur making a "MakeGetRequest", but I failed to access the Requester's Header and change it... Any hint/Advice would be highly appreceited.

Ty in advance.

CarstenLeue commented 1 year ago

Hi @thasyia

First of all, ty for your articles and hard work on the lib - it's awesome.

thank you!

I'm struggling to get my head around "how to change the request header" using http/request funcs.

Do you have the usecase to "change" the header or the usecase to "set" the header? In general I would advise trying to not modify existing objects in the functional world, including the request object. In my example I am using a ReaderIOEither[*http.Request] as the (managed) side effect to create the request.

So as an outline how you'd create an http request with headers you'd create an instance of ReaderIOEither[*http.Request] that does this. A pragmatic (but not clean) way is to start with a MakeGetRequest reader and then use Map to attach the headers (I added an example here: https://github.com/IBM/fp-go/blob/main/context/readerioeither/http/request_test.go#L104). The approach is not really clean, because it mutates the request object from MakeGetRequest.

An alternative approach is to use a builder pattern, i.e. instead of starting with an HttpRequest and then changing it, you'd first assemble all data in a bean, the builder. Each time you "change" a property on the bean you create a new copy. When all config has been set, you convert the bean into a ReaderIOEither[*http.Request] that creates the final request. (I have added an example here: https://github.com/IBM/fp-go/blob/main/context/readerioeither/http/request_test.go#L131).

If I missed the intent of your usecase, please let me know, so I can think about a solution.

thasyia commented 1 year ago

Hi @CarstenLeue,

thank you - this is more than I expected… exactly what I was looking for. My usecase is to set the Header. Many thanks for the new samples and hints about purity and builder pattern.