Redirecting to a new URL using Lambda Function

Hi!

I am writing a Spotify authorization web flow with Netlify’s serverless lambda functions.
I have managed to get them to work locally without error, hosting in port 9000. In production, however, after a successful deployment I am finding that, while the correct characters appear in the browser’s url after activating a click event to one of my lambda functions (eg. siteName/.netlify/functions/functionName), the browser won’t actually load the page and the client is forced to press the page reload button to run the function. The same thing happens when I am redirected back to my create-react-app site from the lambda functions.

This happens on both FireFox and Chrome/Brave and there is no error message. I suspect no problems with the build. I am using 302 redirects which I pass through a handler’s callback, and I suspect they are defining a redirection but not actually navigating there. Is there a way to navigate to a url from within a lambda function? To my knowledge the window and document elements are not accessible. Any help with this would be most appreciated!

Here is an example of what I am using:

exports.handler = function(event, context, callback) {
  const scope = 'user-read-private%20user-read-email%20user-modify-playback-state%20user-read-playback-state%20user-read-recently-played';
  const url = `https://accounts.spotify.com/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}`;

    try {
      return callback(null,{
        statusCode: 301,
        headers: {
          Location: url,
        },
      })
    } catch (err) {
      return callback(null,{ statusCode: 500, body: err.message });
    }

}

My Netlify site name is music-box.netlify.app.

Thanks in advance and I look forward to your reply.
//Dom

Sorry, this isn’t the answer you’re looking for, but, kindly don’t open the same topic twice. There are who will reply if they can help, but, opening multiple topics for the same thing will only lead to confusion. I’ll close the previous topic to avoid duplication. I hope you understand. :slightly_smiling_face:

1 Like

Greetings Dom :wave:t2:

Can you share some of the front-end code? You mentioned a click event or some sort of button the user clicks on? May you share the code around that button please? I imagine this is a case of javascript running AJAX on a page and possibly even setting the current URL but not actually forcing the browser to navigate


Jon

1 Like

Hi Jon,

Thanks for looking into this for me.

I’m not using AJAX explicitly, however I’m not sure if Netlify or one of the packages I use converts the JavaScript somehow to AJAX. What your saying about not forcing the browser to navigate sounds exactly like the problem I’m having.

With the REACT_APP_BACKEND_ENDPOINT environment variable set to “.netlify/functions” in Netlify, the create-react-app frontend looks like this:

const backend_endpoint = process.env.REACT_APP_BACKEND_ENDPOINT;
const LoginPage = () => {
  const url = `${backend_endpoint}/login`;
  return (
    <>
        <a.button
          onClick={() => navigate(url)}
        >
          Sign in to spotify
        </a.button>
    </>
   )
}

Cheers,
//Dom

I’m not exactly sure of all of the specifics in your project, but if you’re just making an anchor that navigate’s onClick, why not just set the href of the anchor instead of wiring up an onClick handler anyway? I think you’re trying to use javascript to do what an anchor already does natively?


Jon

1 Like

The <a.button> tag is from the react-spring package. I could be wrong but I don’t think the problem is the tag or onClick as the problem seems to be occurring from within the lambda functions - it happens for each of the two functions I have, and they’re called differently, one from another lambda function. Is it possible they could be firing some sort of error or warning (not to the client) which could trip the backend server?

I suppose - for starters I’d recommend checking the Function logs in the Netlify Admin back end… but generally I think your Function code is fine and probably returning a 301 (you can verify that from the Network tab of your browser’s dev tools). My gut tells me this is more of a front-end issue with handling that response.

1 Like

I just did a rebuild and my Function Logs don’t print any errors during a forced reload through the functions. One thing that looks odd, though I’m not sure if its normal, is that it says that the function’s endpoint is “https://master--music-box.netlify.app/.netlify/functions/login” rather than “https://music-box.netlify.app/.netlify/functions/login”. Any idea where that “master–” comes from?

I just checked out the Network tab in my dev tools. When I click the onClick the screen goes blank and no request occurs despite the url being populated by the destination. That’s the first line in the below request log. If I force the navigation by clicking page refresh, then the next three lines and more follow. I think the “login” 301 is me physically firing the page refresh button, and then the “authorise” 301 which I call in my function is logged as a 303 “see other” request, likely because it links to another page (Spotify in this case).

After filling in authentication details in Spotify, my “authorise” 301 which I wrote about above gets fired again (no idea why) as a 302 and then Spotify redirects me to my other lambda function via a 301 request. My lambda function then attempts a 301 request which seems to be done as a 304 “Not modified” request instead. Despite the url changing to what it should be, the screen stays blank without error and the navigation isn’t carried out.

After I force a navigation with a second page refresh, the page loads with authorization granted as it should. These final requests are logged as 304 “Not modified” requests.

You can see how the waterfall plots play out to the right. Does any of this fire alarm bells?

hi @d000000m,

Not sure I have an answer either but I’ll try to answer some of your questions.

The master-- denotes the context of a deploy. That just says that that specific function is deployed from the master branch. If that is your production branch, it’s synonymous to your plain subdomain url.

A 304 Not Modified means your browser is using the cached version of the asset that you previous received for that request. Maybe you can add a Cache-Control: no-cache to the headers you are returning from your function?

Let me know if that helps.

Hi Dennis,

Thanks for your help and for your answers.

Ok, great to know that the master-- context is expected.

I have included the no caching to the headers of each of my redirects but unfortunately it doesn’t solve the problem. I managed to solve one of the redirect problems by forcing a window.location.href reload once returning to the frontend, and this may be a workaround for redirects of that kind (ones that send to the frontend). However, I still have the problem that base_url/.netlify/functions/login doesn’t run when it’s first called …only after its reloaded/refreshed.

Hi Dennis,

I have solved this now. It turns out that navigate(), which is a function in the @reach/router React package, isn’t supported by Netlify. When I swapped these functions out for window.location.href = base_url/.netlify/functions/login the code worked.

Thanks for your help throughout.

// Dom

Hi Jon,

I have solved this now. It turns out that navigate(), which is a function in the @reach/router React package, isn’t supported by Netlify. When I swapped these functions out for window.location.href = base_url/.netlify/functions/login the code worked.

Revisiting this comment you wrote I can’t believe I overlooked earlier your correct solution. I was convinced that the problem was occurring inside the lambda functions, where the window element is not attainable, as refreshes were needed both entering and returning from the lambda functions. Turns out it these refreshes were caused by different issues.

Thanks for your help throughout.

// Dom

1 Like

No problem. And yes, navigate() as used in the @reach/router and subsequently Gatsby and many other projects, is only used for assets and pages internal to that project (…stuff that’s created as a result of the project build itself) – since the Function, while mounted on a path of the site’s domain / available on the same URL, is not actually part of the project, navigate() would fail and cause strange effects (which you saw). You would indeed need to implement an assignment to window.location (you can skip the .href if you prefer :stuck_out_tongue: ) – this prompts a full browser navigation and allows the browser to operate in its own native capacity. I actually just had to implement this yesterday in another project! :grin:

Glad we got there!


Jon