Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Apps | Demo | Docs | Install
  1. Cloudron Forum
  2. Ghost
  3. /members/api/send-magic-link gives a 404, blocking member signup

/members/api/send-magic-link gives a 404, blocking member signup

Scheduled Pinned Locked Moved Solved Ghost
5 Posts 3 Posters 1.9k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • kaxlineK Offline
      kaxlineK Offline
      kaxline
      wrote on last edited by
      #1

      Hey there, I have an unorthodox setup for Ghost and Surfer that may be causing problems.

      The current issue is that users cannot signup for Ghost membership via the usual request in the Ghost frontend:

      members/api/send-magic-link/

      My blog is at

      https://re-public.io/blog

      If you want to see for yourself.

      This problem may come from Cloudflare since I'm using a worker to re-write requests:

      // Config for our subdomain (where the Ghost blog currently lives)
      // and our root domain (where we want it to live)
      // and our blogPath (the subdirectory we want it at)
      // Change these to suit your case!
      const config = {
        subdomain: "blog.re-public.io",
        root: "re-public.io",
        blogPath: "blog",
      }
      
      // Function that processes requests to the URL the worker is at
      async function handleRequest(request) {
        // Grab the request URL's pathname, we'll use it later
        const url = new URL(request.url)
        const targetPath = url.pathname
      
        console.log(`https://${config.subdomain}${targetPath}`)
      
        // Change request URLs to go through to the subdomain
        let response = await fetch(`https://${config.subdomain}${targetPath}`)
      
        // Ghost loads assets like JS and CSS from 3 subdirectories
        // We don't need to change these requests at all
        // So if we're getting stuff from those subdirectories,
        // we return the response of the fetch request from above
        // immediately.
        if (
          targetPath.includes('/${config.blogPath}/sitemap.xsl') ||
          targetPath.includes(`/${config.blogPath}/assets/`) ||
          targetPath.includes(`/${config.blogPath}/public/`) ||
          targetPath.includes(`/${config.blogPath}/content/`)
        ) {
          console.log(targetPath)
          return response
        }
      
        // In other cases - which will usually be pages of the
        // Ghost blog - we want to find any reference to our subdomain
        // and replace it with our root domain.
        // This is so that things like our canonical URLs and links are
        // set up correctly, so we NEVER see our subdirectory in the code.
      
        // First we get the body of the response from above
        let body = await response.text()
        // Then we search in the body to replace the subdomain everywhere
        // with the root domain.
        body = body.split(config.subdomain).join(config.root)
      
        response = new Response(body, response)
        return response
      }
      
      addEventListener("fetch", (event) => {
        event.respondWith(handleRequest(event.request))
      })
      

      Why would I do this? Well I am serving a Surfer static site from Cloudron at

      https://re-public.io

      And I don't want to fork off the blog to a subdomain for SEO purposes, which members helped me solve in a previous issue, via this Cloudflare solution:

      https://forum.cloudron.io/topic/6713/where-can-i-put-custom-nginx-conf-that-won-t-be-overwritten

      There are no errors in the Ghost logs in the Cloudron package instance, it just logs a 404 when members/api/send-magic-link/ is hit.

      I'm not sure if this is a Cloudflare, Ghost, or Cloudron issue, or a combination of all three. I would really appreciate any guidance on how to debug or suggestions on a fix.

      Thank you!

      girishG 2 Replies Last reply
      0
      • kaxlineK kaxline

        Hey there, I have an unorthodox setup for Ghost and Surfer that may be causing problems.

        The current issue is that users cannot signup for Ghost membership via the usual request in the Ghost frontend:

        members/api/send-magic-link/

        My blog is at

        https://re-public.io/blog

        If you want to see for yourself.

        This problem may come from Cloudflare since I'm using a worker to re-write requests:

        // Config for our subdomain (where the Ghost blog currently lives)
        // and our root domain (where we want it to live)
        // and our blogPath (the subdirectory we want it at)
        // Change these to suit your case!
        const config = {
          subdomain: "blog.re-public.io",
          root: "re-public.io",
          blogPath: "blog",
        }
        
        // Function that processes requests to the URL the worker is at
        async function handleRequest(request) {
          // Grab the request URL's pathname, we'll use it later
          const url = new URL(request.url)
          const targetPath = url.pathname
        
          console.log(`https://${config.subdomain}${targetPath}`)
        
          // Change request URLs to go through to the subdomain
          let response = await fetch(`https://${config.subdomain}${targetPath}`)
        
          // Ghost loads assets like JS and CSS from 3 subdirectories
          // We don't need to change these requests at all
          // So if we're getting stuff from those subdirectories,
          // we return the response of the fetch request from above
          // immediately.
          if (
            targetPath.includes('/${config.blogPath}/sitemap.xsl') ||
            targetPath.includes(`/${config.blogPath}/assets/`) ||
            targetPath.includes(`/${config.blogPath}/public/`) ||
            targetPath.includes(`/${config.blogPath}/content/`)
          ) {
            console.log(targetPath)
            return response
          }
        
          // In other cases - which will usually be pages of the
          // Ghost blog - we want to find any reference to our subdomain
          // and replace it with our root domain.
          // This is so that things like our canonical URLs and links are
          // set up correctly, so we NEVER see our subdirectory in the code.
        
          // First we get the body of the response from above
          let body = await response.text()
          // Then we search in the body to replace the subdomain everywhere
          // with the root domain.
          body = body.split(config.subdomain).join(config.root)
        
          response = new Response(body, response)
          return response
        }
        
        addEventListener("fetch", (event) => {
          event.respondWith(handleRequest(event.request))
        })
        

        Why would I do this? Well I am serving a Surfer static site from Cloudron at

        https://re-public.io

        And I don't want to fork off the blog to a subdomain for SEO purposes, which members helped me solve in a previous issue, via this Cloudflare solution:

        https://forum.cloudron.io/topic/6713/where-can-i-put-custom-nginx-conf-that-won-t-be-overwritten

        There are no errors in the Ghost logs in the Cloudron package instance, it just logs a 404 when members/api/send-magic-link/ is hit.

        I'm not sure if this is a Cloudflare, Ghost, or Cloudron issue, or a combination of all three. I would really appreciate any guidance on how to debug or suggestions on a fix.

        Thank you!

        girishG Offline
        girishG Offline
        girish
        Staff
        wrote on last edited by girish
        #2

        @kaxline Just taking a wild guess here without knowing much about Ghost or Cloudflare workers. I just searched the code and I found this here https://github.com/TryGhost/Ghost/blob/c7b247a07943bd95d5c83e0840e8c4f5d0069af2/test/e2e-frontend/members.test.js:

                it('should error for invalid data on member magic link endpoint', async function () {
                    await request.post('/members/api/send-magic-link')
                        .expect(400);
                });
        

        So, it seems it's a POST request. In your Cloudflare worker code, you use await fetch which I think does only GET request, correct? Could that be the issue ?

        1 Reply Last reply
        1
        • kaxlineK kaxline

          Hey there, I have an unorthodox setup for Ghost and Surfer that may be causing problems.

          The current issue is that users cannot signup for Ghost membership via the usual request in the Ghost frontend:

          members/api/send-magic-link/

          My blog is at

          https://re-public.io/blog

          If you want to see for yourself.

          This problem may come from Cloudflare since I'm using a worker to re-write requests:

          // Config for our subdomain (where the Ghost blog currently lives)
          // and our root domain (where we want it to live)
          // and our blogPath (the subdirectory we want it at)
          // Change these to suit your case!
          const config = {
            subdomain: "blog.re-public.io",
            root: "re-public.io",
            blogPath: "blog",
          }
          
          // Function that processes requests to the URL the worker is at
          async function handleRequest(request) {
            // Grab the request URL's pathname, we'll use it later
            const url = new URL(request.url)
            const targetPath = url.pathname
          
            console.log(`https://${config.subdomain}${targetPath}`)
          
            // Change request URLs to go through to the subdomain
            let response = await fetch(`https://${config.subdomain}${targetPath}`)
          
            // Ghost loads assets like JS and CSS from 3 subdirectories
            // We don't need to change these requests at all
            // So if we're getting stuff from those subdirectories,
            // we return the response of the fetch request from above
            // immediately.
            if (
              targetPath.includes('/${config.blogPath}/sitemap.xsl') ||
              targetPath.includes(`/${config.blogPath}/assets/`) ||
              targetPath.includes(`/${config.blogPath}/public/`) ||
              targetPath.includes(`/${config.blogPath}/content/`)
            ) {
              console.log(targetPath)
              return response
            }
          
            // In other cases - which will usually be pages of the
            // Ghost blog - we want to find any reference to our subdomain
            // and replace it with our root domain.
            // This is so that things like our canonical URLs and links are
            // set up correctly, so we NEVER see our subdirectory in the code.
          
            // First we get the body of the response from above
            let body = await response.text()
            // Then we search in the body to replace the subdomain everywhere
            // with the root domain.
            body = body.split(config.subdomain).join(config.root)
          
            response = new Response(body, response)
            return response
          }
          
          addEventListener("fetch", (event) => {
            event.respondWith(handleRequest(event.request))
          })
          

          Why would I do this? Well I am serving a Surfer static site from Cloudron at

          https://re-public.io

          And I don't want to fork off the blog to a subdomain for SEO purposes, which members helped me solve in a previous issue, via this Cloudflare solution:

          https://forum.cloudron.io/topic/6713/where-can-i-put-custom-nginx-conf-that-won-t-be-overwritten

          There are no errors in the Ghost logs in the Cloudron package instance, it just logs a 404 when members/api/send-magic-link/ is hit.

          I'm not sure if this is a Cloudflare, Ghost, or Cloudron issue, or a combination of all three. I would really appreciate any guidance on how to debug or suggestions on a fix.

          Thank you!

          girishG Offline
          girishG Offline
          girish
          Staff
          wrote on last edited by
          #3

          @kaxline It seems you have to pass 'method' and the body in Cloudflare worker like https://stackoverflow.com/questions/39565706/post-request-with-fetch-api

          kaxlineK 1 Reply Last reply
          0
          • girishG girish

            @kaxline It seems you have to pass 'method' and the body in Cloudflare worker like https://stackoverflow.com/questions/39565706/post-request-with-fetch-api

            kaxlineK Offline
            kaxlineK Offline
            kaxline
            wrote on last edited by
            #4

            @girish Yep, that was it, thank you! That's something I should've caught but my mind wasn't sure where to start looking for the problem.

            Huge time saver!

            1 Reply Last reply
            0
            • robiR Offline
              robiR Offline
              robi
              wrote on last edited by
              #5

              @girish that was an amazing wild guess 😏

              @kaxline if you can post the final solution, it will be findable by others later. 🙏

              Conscious tech

              1 Reply Last reply
              1
              • girishG girish marked this topic as a question on
              • girishG girish has marked this topic as solved on
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Bookmarks
                • Search