So I have an REST endpoint that accepts a yml file, converts it into a struct and saves it into a Database ( Mongo DB ).
This is what the file looks like:
_id: someID
name: someName
multiline: |>
blah blah many lines
blah blah many lines
blah blah many lines
blah blah many lines
prop: 1
Then I have another endpoint that reverses this process and actually returns a file from that "id". Like:
func (h SomeHandler) DownloadAsFile(w http.ResponseWriter, r *http.Request) {
someID := chi.URLParam(r, "someId")
obj, err := h.usecase.GetObj(r.Context(), someID)
// ... handles error....
bys, err := yaml.Marshal(obj)
// ... handles error....
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.yml", ruleName))
w.Header().Set("Content-Type", "application/octet-stream; charset=utf8")
w.Header().Add("Content-Type", "charset=utf8")
w.WriteHeader(http.StatusOK)
render.Data(w, r, bys)
}
This all works really well and I can go to my endpoint at : http://myservice.com/download/12345
And both Chrome and Postman download the file with no issues.
BUT, there is something going on with the encoding, because I see that in the newly downloaded file, I get this:
_id: someID
name: someName
multiline: |4
blah blah many lines
blah blah many lines
blah blah many lines
blah blah many lines
prop: 1
If you take a look, you can notice the ">" was converted to a "4". If I copy paste this into a YAMl online validator, it says its a valid one. But why is the symbol ">" changing? I am affraid that other symbols I did not notice changed too.
In yaml there are two Block Scalar
styles:
|
, literal: Keeps new lines>
, folded: Folds (removes) new lines if next line is not empty newline.Look at this site, it's great.
You should not use |
and >
at the same time, it's not valid yaml. go-yaml parses it correctly ( says it's not valid). One of the yaml validators on the web, said it's valid but their vs-code like text component said it's error :), probably your library/version incorrectly parses it.
Look at below from YAML Spec
[199] s-l+block-scalar(n,c) ::=
s-separate(n+1,c)
(
c-ns-properties(n+1,c)
s-separate(n+1,c)
)?
(
c-l+literal(n)
| c-l+folded(n)
)
Also I'd just deal with newline escape for multiline strings, and use json. Dealing with yaml is pain, json is much simpler and enough for many nearly every cases. This is just personal preference, but I won't use yaml If there's no commentation need like: "Don't change this line, or prod will down". Since you just serialize/deserialize, json looks simpler choice. My 2 cents though, of course I have no idea on your use case :)