mit-teaching-systems-lab / threeflows

Practice spaces for teacher preparation programs
https://tsl.mit.edu/
MIT License
8 stars 9 forks source link

How to redirect to a variable address? #373

Open keving17 opened 6 years ago

keving17 commented 6 years ago

I'm working on creating sessions and having shareLinks redirect to some longer url. That way, a teacher educator can say they want to use the Turner scenario and give the site: https://teachermoments.teachingsystemslab.org/teachermoments/turner?fromdemos

and get back a unique share link to give out to students: _https://teachermoments.teachingsystemslab.org/share/[some_random_string]_

instead of having to tell students to go to the longer actual link: _https://teachermoments.teachingsystemslab.org/teachermoments/turner?fromdemos&share=[the_same_random_string_from_before]_

The form looks like this:

screen shot 2018-06-10 at 7 23 51 pm

I can generate the share links. And I have a database that connects the unique share links to their actual link. I have a page that shows what it should be redirecting to but I can't get the page to redirect.

screen shot 2018-06-10 at 7 17 04 pm

I've looked at the enforceHTTPS in index.js but I still don't know where I'm going wrong. In inspecting the browser, I can see the 302 for redirecting and a 200 on redirect link but I can't figure out why it doesn't go to the page.

screen shot 2018-06-10 at 7 19 17 pm screen shot 2018-06-10 at 7 21 12 pm

Any clues @kevinrobinson ? Code can be found here: https://github.com/mit-teaching-systems-lab/threeflows/tree/patch/createSession

kevinrobinson commented 6 years ago

@keving17 Awesome progress! This looks great overall and nice description of what's going on 👍

Reading through the code quickly, it looks like the "create" flow has all the pieces. For /share/:shareId if the redirect happens on the server side, that would let you remove some UI code and intermediate steps. That way, when a student requests that URL in their browser, the server responds with a redirect and the UI code doesn't have to be involved at all.

So that would mean changing the /server/research/share server route in index.js to be /share/:shareId, and having that call the code you have in redirectShare.

Right now, the chain of what is happening is:

  1. user visits /share/4 and the server matches the "I don't know that route" code and sends down the HTML page with the JS code.
  2. the JS code runs and App.js routes to CreateSharePage.
  3. CreateSharePage runs and makes a fetch request where it asks specifically for JSON. You can see that in Web Inspector under the "type" column or in the request/response headers.
  4. The server calls that redirect code, but it doesn't work right since it's a JSON request and it's ultimately just sending that data back to your JS code in CreateSharePage.

What you're thinking here could work, you could have the server just send back the URL it should redirect to, and have CreateSharePage grab that from the response and navigate to window.location = redirectUrl. But my suggestion would be to do the server-side redirect which will let you remove some steps and the related UI code altogether.

keving17 commented 6 years ago

Ok. So I think I understand what you're saying. We should be able to make the entire interaction purely server-side.

However, I'm still a bit lost on how to make this work. I feel like I can't get response.redirect(path) to work as intended.

The idea is to get rid of all of the code I have in client. and change the index.js in server to have

app.get('/share/:shareId', redirectShare.bind(null, pool));

which should catch things like http://localhost:3000/share/76427c74-bdae-4374-a5de-fcd7596f8a7a and redirect them to the appropriate urls using

pool.query(sql,values)
    .then(redirectLink => {
        return response.redirect(redirectLink);
    });
kevinrobinson commented 6 years ago

Yep, that sounds like the big pieces!

One important thing is that if your JavaScript code is making a fetch request and asking the server for JSON, if the server code says response.redirect(url), your JS code probably isn't written to expect that and then redirect the browser. That might be what you're running into. If the browser makes a request (like, you click a link or the person types in a URL), and the server responds with response.redirect(url), the browser will know what to do with that and it will do the redirect.

To debug this, open up Web Inspector and check out the response codes and response headers. When you write server code like response.redirect('https://kevin.com/'), what that does is sends back a 302 response status (which the browser knows means "redirect!") and a response header Location: http://kevin.com/ (which the browser reads to know where the redirect should go to).

Here's what it looks like for the http > https redirect when you request http:// something:

screen shot 2018-06-15 at 8 48 53 am

and if you click in to look at the response headers, you can see the redirect location uses https:// and the browser follows it:

screen shot 2018-06-15 at 8 49 06 am