0

I'm working on a personal project to learn some more Go and hitting a snag (or potentially going about this all wrong too so there is that).

A little background first: I'm working on a simple web app with some form fields to do some basic network tests like curl, netcat, and traceroute. I was looking to use WASM so that I could just modify the DOM with results from the Go app, but I believe due to there being a lot of syscalls, the WASM architecture doesnt support them and I couldnt compile it after a certain point or when it did it was failing anytime I ventured into some of the network pkgs. I couldn't really find another way to use javascript without abandoning Go, so I decided to go with templates.

When a form is submitted it loads a results.html that is identical to the index.html except some Go templating to print the results of the network tests. It works great has a "meh" kinda of way to simulate JS modifications and allow you to do more tests without leaving the page BUT since there are three different network tests, and only one running at one time, I get errors when it can't fill ALL the templates.

So for example

  <section id="curlOutput">
    <p><strong>Executed curl to {{.URL}}</strong></p>
    <p>{{.Protocol}}</p>
    <p>{{.Status}}</p>
    <p>{{.ContentLength}}</p>
    {{range $key, $val := .Headers}}
    <p><strong>{{$key}}:</strong> {{$val}}</p>
    {{end}}
    <br/>
  </section>

  <section id="ncOutput">
    <p><strong>Executed netcat to {{.Host}}</strong></p>
    <p>{{.Result}}</p>
  </section>

The issue i hit is if I want to test Netcat, Go throws errors because it can't fill the earlier templates like for curl and such. So is there a way to define in the templates that if the value doesnt exist, just continue and leave it blank? Or does every single template have to be defined and filled? Perhaps defining defaults in the templates to be empty strings somehow? Is there a better way to go about this in general?

Sorry for the length, but i felt some background would help, thanks!

Tony
  • 23
  • 1
  • 2
  • 3
    Use `{{if .URL}} ... {{end}}`. Check the documentation for template package. – Burak Serdar Mar 22 '21 at 21:55
  • I actually saw that and gave it a shot but still get an error: `result.html:16:7: executing "result.html" at <.URL>: can't evaluate field URL in type v1.NetcatOutput` Digging some more I think I get the issue now, there is no URL field in my output struct for netcat, only curl. Saw this Answer, might have to look into this unless there is a better option/idea. Thinking a common struct field like "funcID" would help. https://stackoverflow.com/a/44676179/6646057 – Tony Mar 22 '21 at 23:10
  • 1
    It's weird to me that the template's data varies with the function called, but the template itself is shared. Shouldn't you have template snippets that go along with the different functions and their data? And then maybe you could include that template in? This might give you some ideas :https://www.calhoun.io/intro-to-templates-p2-actions/ – erik258 Mar 23 '21 at 01:24
  • "if the value doesnt exist" is your problem. That is too vague! Come up with a clear, proper, technical definition of "doesnt exist" and the solution in the template will be obvious. For strings ""doesnt exist" could mean being equal to "". Or it could mean a pointer to the string is nil or it could mean a map value doesn't contain that key, etc. pp. Once you understand what ""doesnt exist" really means it is dead simple to check this in the template – Volker Mar 23 '21 at 05:22

1 Answers1

2

You can use a data struct better suited for the task and the with template action.

type Results struct {
    CURLOutput *CURLOutput
    NCOutput   *NCOutput
}

type CURLOutput struct {
    URL           string
    Protocol      string
    Status        string
    ContentLength int64
    Headers       map[string][]string
}

type NCOutput struct {
    Host   string
    Result string
}
{{- with .CURLOutput -}}
<section id="curlOutput">
    <p><strong>Executed curl to {{.URL}}</strong></p>
    <p>{{.Protocol}}</p>
    <p>{{.Status}}</p>
    <p>{{.ContentLength}}</p>
    {{ range $key, $val := .Headers -}}
    <p><strong>{{$key}}:</strong> {{$val}}</p>
    {{- end }}
    <br/>
</section>
{{ end }}
{{ with .NCOutput -}}
  <section id="ncOutput">
    <p><strong>Executed netcat to {{.Host}}</strong></p>
    <p>{{.Result}}</p>
</section>
{{ end }}

https://play.golang.org/p/dOfLc_5bl8b

mkopriva
  • 35,176
  • 4
  • 57
  • 71
  • 1
    This solved my issue, thanks! Eventually I'd like to go back and see if I can get WASM and JS to work since this feels like not the best way to go about it, but I just wanted to get everything else working first. – Tony Mar 23 '21 at 12:48