Issues with transitioning from index html page to city html after user enters search critieria
I'm having issues with my route where the user enters their search and after pressing enter, the url changes but the redirect isnt happening. The content is displaying on the index.html page when it isn't suppose to. Here is a link to the github of the current standing of the project
https://github.com/MD-2016/Weather-App/
There is also an issue with the http request with the log
http: superfluous response.WriteHeader call from main.search (main.go:77)
showing up. The issue is starting in main.go
Thank you for your time looking into my issue 🙂GitHub
GitHub - MD-2016/Weather-App: A weather app using a third party api...
A weather app using a third party api with the goal being a build upon project with additional features as time goes on. - GitHub - MD-2016/Weather-App: A weather app using a third party api with t...
174 Replies
superfluous response.WriteHeaderthis simply means that a response header has already been written and you're trying to re-write but that cannot be done don't use numbers for your status check, go has consts for that
which part is being written twice?
temp.Execute(w, weatherResponse) Execute applies a parsed template to the specified data object, writing the output to wr
ah ok
when you execute, that writes to your response writer
thing is though how do I get the redirect to trigger after their search input?
http://localhost:8080/search?searchBox=Lexington
that's what the URL does and the page stays same doesnt go to city.html
do I need a route for it too?instead it's inserting the code into my index.html page
🤔
I'm not sure what setup you have or what you're trying to do, but why not redirect before executing the template
I had it like that before and it didnt work
removing the redirect actually removed the previous error
why doesn't it work?
do you not have a handler for the results of the search?
I just don't know what you're trying to do
so my goal is this....
1. user enters their search request and hits enter
2. The api call is made and gets the request
3. The user is redirected to the page that displays the results of the call which is the data parsed onto the page (city.html)
I made the needed struct to handle the json conversion
I made a template on the city.html to display it
why is the call made outside of the page tho?
it should redirect, the handler get the searched city, make the call, parse the template, boom
I just had a separate page to display the data and hourly and such and then the url would change over to that city
your page should be dynamic in the sense that if a person simply goes to
yourpage.com/search=nyc
that works
in your setup only if they use the search bar it works
because the search is the one doing the call as opposed to the page requestedoh
what should I change then?
I was trying to make in style like common weather websites do
where you get redirected after search inpout
*input
The Weather Channel
National and Local Weather Radar, Daily Forecast, Hurricane and inf...
The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage
yeah but if you share the resulting url it works
in your case it wouldn't
https://weather.com/weather/today/l/6650126154c3859cadd982cf2aad0aa3efb05df3558f6d50b8ac52bd96e17d52
The Weather Channel
Beverly Hills, CA Weather Forecast and Conditions - The Weather Cha...
Today’s and tonight’s Beverly Hills, CA weather forecast, weather conditions and Doppler radar from The Weather Channel and Weather.com
oh 😦
im trying to avoid js for this project
you don't need js
your search bar is just...alone?
/search
is just the searchbar?yeah being backend project I didnt wanna build a lot because it isnt a full stack project
yes
did I do too much for this level of project?
nah
you have a couple of options for this
im just happy I got as far as I have
with what little time ive gotten lately
you can dooooo
hmmm
well looking at what weather.com does you could prolly setup 2 handlers
does my code look sloppy or more readable this time?
one for
/search
and one for /search/{city}
so the search handler renders the search bar and redirect to whatever search was done by the user and /search/nyc
renders the page for new york cityyeah that was my original goal
but didnt know how to do it
it looks fine,tho you're not always looking for errors
pretty sure this would work
and from
r.URL.Path
you get the last bit of the url which should be the cityhmm ok
so I cut out code from the search
🤔
like the redirect and such
I have your gh repo no need to send code again
my guess is return the
weatherResponse
to pass into the searchCityHandler
the /search page only renders the searchbar and the searchbar redirects to the
/search/los-angeles
url
nowell in this case err
your city handler makes the call, you do not get the api call from anywhere else
all your searchbar should do is redirect to the correct page that is their whole job
ah ok so take out that api call then
yes
and when the city page is requested it makes the call and renders the page with the data
that's it
ah so like this
yeah, not sure about the url tho
also the redirect func can only have 3xx codes
so not statusok
The provided code should be in the 3xx range and is usually StatusMovedPermanently, StatusFound or StatusSeeOther.
weird
vscode shows 4 on hover over
code int
yes that's fine
I didn't say remove it entirely
just not the ok status code
like...
another code
a 3xx code
the ones that are for redirects
you can't redirect and say "ok" that's not what that is for
like 302
"found"
you prolly want the "statusFound"
yes
sadly not sure how I handle the passing of the search bar input to the next route
you grab the input
redirect to
search/{input}
that's why I said I wasn't sure about the urlURL === best state management
nerd came in here just to say that
hmm
ok ill have to see but my go knowledge is limited so
I did xD
cause its important 😄
pretty sure you just gotta
http.Redirect(w, r, "/search/nyc", http.StatusFound)
ofc the string gotta be dynamic but u get the pointah
so in my case the "userinput.UserInput"
ye
might have to use fmt Sprintf
that should do it
now the challenge is getting that "city" result to the searchcityHandler
this is how it looks so far
just not sure how the
searchBox
input is going to the api call from /search
to /search/{city}
doesn't this code look fun B1? xDno and its why I pref file/folder based routing xD
crap same issues are arising
url never changed over
localhost:8080/search?searchBox=Lexington
imagine your routing being messed up so the page you're suppose to go never happens and you end up in the same page but the html code from that page your suppose to go to is showing up in your current page
basically inserting code into it because it can 😄first of all
"/search/{city}"
I don't think that does what you think it doesyeah it's not
dat succs and also different usecase
the other issue is the "/" route
why would that be an issue
because it's doing template processing too
It's easy to know what does what where, also you can always hijack it in middleware to do hacky stuffs.
2 routes doing same "execute"
I thought the url redirection would trigger the "/search/{city}" search City Handler
guess not 😄
it's probably something stupid
it always is
I guess the
searchCityHandler
route isn't triggeringcould it be because you are using the same route?
both main and it
or start rather?
it probably doesn't know what
{city}
is in mainfirst of all you need to understand how the pattern match works
https://pkg.go.dev/net/http#ServeMux
this is why I study languages and such in more depth so I understand the concepts more
and again,
/search/{city}
doesn't do what you think it does
you're matching the literal url page.com/search/{city}
that is not a variablethat's where im confused
how to trigger the routes correctly and how they work
main probably doesnt know what "city" is
read
ah
r.URL.Path
?yes
so this needs changed?
http.HandleFunc("/search/{city}", searchCityHandler)
I added this
http.Redirect(w, r, r.URL.Path, http.StatusFound)
so far the redirecting is failingwhat
idk where or why you added this but no
/search/
just that, that's your patternso
/search
vs /search/
you have a
/search
and a /search/
one goes to the main search page, the other goes to anything with a subpath AKA /search/nyc
or /search/la
yes
ok so
when the user types enter after their input
this is the route
http://localhost:8080/search?searchBox=Lexington
so this needs to become /search/Lexington
but be city.html
pageI-
I'm lost
the redirect should happen as the last thing on the
/search
correct?
there's just something here im not doing correctly
I think searchCityHandler
is ok
it's searchHandler
something isn't going right
either I get errors about the redirect from firefox not working correctly or it doesnt happen
sadly debugging tool on vscode isnt working properly
sorry im not understanding well Erick. This is new territory for mehmmmm
thinking
StackHawk
Golang Open Redirect Guide: Examples and Prevention
An explanation of Golang open redirect vulnerabilities with a few examples of risky code and how to fix it.
that's not relevant
ok
how about I make this easier
what is your main page?
the index.html
was trying this too
http.Redirect(w, r, "localhost:8080/search/", http.StatusFound)
don't do absolute paths
ok
let's ditch the subpaths
let's make it easier and use queries
here's the basic idea read this carefully
you will have one handler for the
/search
page, you are going to check for queries using the r.URL.Query().Get("city")
method, IF there is no query that means it is either an invalid query or just the base page /search
so all you need to do is render the input and absolutely nothing else, your input is going to make a GET request something like:
when the user submits this the form will make a GET request that looks like: /search?city=new+york
, THEN the EXACT SAME handler will be called but this time using r.URL.Query().Get("city")
you WILL have a valid query, at that point you make whatever API call you need to make and return the page that renders the results of said input.this makes me sad
but ill try it
huh
but like...why
yeah the searchBox is the name of the input on index.html
what?
well that's a bad name cause it tells you nothing about what the input is for
the a11y tree also takes this name into account if there's no label
also I did
type="text"
but a type of search is better for this inputthis all ive done so far
so change the
/search
to r.URL.Query().Get("city")
?uh
you don't have to parse the form only get the query on the url
no redirect needed either
so where does the data go?
city.html is useless?
at this point im just lost
think
what you get from the query?
idk
I havent figured out how to use the query yet
googling it
might just write the function inside main
what are you parsing the form for
which form even
I ask again, what info do you get from the query?
idk anymore
man
go take a break
I was confused with the routes now with the query im lost
This is where I would just look at any tutorial that has routing and learn from it then put the logic in your project
this is what im currently getting
without the query
http://localhost:8080/search?city=Lexington
do you understand what a url query is?
inserted elements into a url?
to help filter and such
ok show me a query
https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
Its just a key:value pair MD
?key=value
thats it
sorry my mind is toast
So in Go you should be able to use the r.URL.Query().Get("city") or what ever to get ?city=
I get that but im not seeing where I put that code
not in "/search"
but I guess in searchHandler
right but in /search/
cause you would have search/?city=value
I don't like that mehtod but its what Erick was leading you to so I don't wanna deviate
ofc in the handler
typically I would have it without trailing slase
what method would you use?
oh no trailing slash needed
but you would needf to havea different /search for home
/search
is finesorry had to get bug spray some files are annoying me
ok
ok what md
walk me through your ideas
here's what i got so far in
main.go
in the main function
so as b1 stated the /search/
is dealing with r.URL.Query().Get()
since the query is search?city="some city"
so to start am i dumping the searchCityHandler?
this is the code for the two handlers
so my questions are the following
is the searchCityHandler
inside the HandleFunc
changing?
is the r.Form.Get
inside searchHandler
changing?NOOOOOO
read carefully for the love of god, you miss half my messages
I didn't state that you did I just repeated it (from what you had in your code) xD
which is also why I said I wouldn't do it that way with a trailing slash
I said
/search
is fine, I stated already that we would have ONE handler
and I told you what that handler would do
so re-read
you have 1 page, MD /search
and there is 2 possible states... no query page.com/search
and query page.com/search?city=new+york
so you handle both cases in 1 handler
if there's no query what is it then? just the search page! if there's a query what is it? the results (either good results or 404) but the results!ok
so you need to check what to know which of the 2 states it is in?
so empty or non empty query
would it be empty string or nil?
empty string
so this?
only errors and pointers can be nil and since it returns a string it'll be empty if nothing is found
you're still parsing the form for no reason, what is that parse for?
it was the only code parsing before sorry
if r.URL.Query().Get("city") == ""
formatinput.FormatWeatherApiCall(r.URL.Query().Get("city"))
just save that in a variable don't check twice
anyway yescould you please explain that again
sorry
you are calling the same method twice
one for the
if
and another time for your FormatWeatherAPICall function
just save it in a variable
oh ok
I wish I could redirect though because all my templating is on the city.html
that's where I have the display setup for the response with tables and such
I guess I could copy and paste into index
should I do a 404 or something for empty?
weird I got EOF
this here hit EOF
looks like the url is formatted correctly
but
the response is EOF
err is EOF
EOF is end of function
Check parentheses and stuff
I come back to this later
closing up for the night let's try this again tomorrow night or something
been running checks on the request and it gets a status 200
not finding the EOF yet
I did take a sample request from the website api explorer and took a json result and had a tool convert my json to the appropriate go struct to handle it and it matched
according to my error checking with println's, the error is happening in the Decoder for the JSON
so im not sure what's going on here 🤷♂️
yep just did a a response check and it came back 200 as the status code
wtf is this supposed to be
so something isnt right either on the close or decoding but when I was doing the decoding and placed a print statement inside the if for decode, it came back as EOF
that's a response print
so my api call is correct getting a 200
that is not json my brother in christ
if you're trying to decode that it will fail
ik it's the result of the http.Get call
but the status code of 200 is a good sign
no
it isn't
just like you tried to set a redirect to 200 because you don't know much about http codes, the same can happen with anyone
for all you know the code 200 and the returned json is {error: "bad response}
because people make shitty APIs
check the payload no the response
so how do find where the EOF is happening
couldnt get debug to work on the searchHandler function
only on main
ok there's a few things wrong here
this makes 0 sense
how are you gonna check for
res
and not err
but log err
?
for all you know err
is empty and you will log nothingjust change to err != nil?
ideally check both
err and status code
and I told you this yesterday, don't use numbers for the status codes there are constants for that
if res.StatusCode != 200 {
badStatusAccepted?
if err := json.NewDecoder(r.Body).Decode(&weatherRes); err != nil {
if err := json.NewDecoder(r.Body).Decode(&weatherRes); err != nil {
this is your issue
no
statusok
learn http codes
take a look at this slowly
what are you decoding here?my goal is to decode the returned json into my struct
and what are you actually decoding here?
look at it carefully
empty body?
nope
what variable is that?
where is
r
coming from?😄
should be
res
yup
res.Body
ok
now I need to display that on the page
or trigger a route
since page went blank after
got a return
and that's uh...
expected?
idk what the response should look like
yeah for my api call
ok
I just need to parse that into the webpage
then all you have left is actually rendering stuff to the screen
yup
so after my input, the screen goes blank
so I need to do another route?
you just need to parse a template
same as with the other routes
but passing your data
so does the
/search
need to change to /search/
we've been over this
no
that handler will parse both templates
just a matter of which part of the
if
you're inyeah but im not sure about something
which is...
im not sure how to bring back the page to display the data
since this a blank page on the route
already have rendering setup in the html
exact same thing you were doing already
you parse and execute a template
ill see how it goes