2

我有一個名爲api的基於express.js的基於firebase的雲功能應用程序。要使用自定義域名,我嘗試使用Firebase Hosting重寫功能將特定網址路由到該功能。 我下面講的雲功能和火力地堡託管在這裏,https://firebase.google.com/docs/hosting/functions官方文檔,並且已經嘗試了許多組合,包括以下內容:帶有動態雲功能的Firebase主機重寫

"rewrites": [ 
     { 
     "source": "/api/**", 
     "function": "api" 
     } 
    ] 

"rewrites": [ 
     { 
     "source": "/api/:path1/:dat1/dat", 
     "function": "api/:path1/:dat1/dat" 
     } 
    ] 
"rewrites": [ 
     { 
     "source": "/api/path1/dat1/dat", 
     "function": "api" 
     } 
    ] 
"rewrites": [ 
     { 
     "source": "/api/*/*/*", 
     "function": "api" 
     } 
    ] 

可悲的是,它似乎並不爲任何可能的組合工作。 我明確的應用程序有以下GET路徑我打算使用:類似這些

'/api/users/:userId/:userData' 
'/api/users/:userId/:userData/json' 
'/api/users/:userId/' 

等。的:帳戶及:用戶數據都在我的請求,參數,可以作爲它的工作原理與express.js

所需的功能按預期在

https://my-firebase-app.cloudfunctions.net 

,但他們不工作

https://my-app.firebaseapp.com 

請告訴我這些應該如何工作,我做錯了什麼。

編輯: 這裏是什麼我的雲功能,出口看起來像

const functions = require('firebase-functions'); 
const express = require('express'); 
const app = express(); 

app.get('/users/:userId/:userData/json', (req, res) => { 
    // Do App stuff here 
} 
// A couple more app.get in the same format 

exports.api = functions.https.onRequest(app); 

編輯樣品2: @ DougStevenson的建議之後,我嘗試了以下配置

我想在下面的我firebase.json,

{ 
    "hosting": { 
    "rewrites": [ 
     { 
     "source": "/api", 
     "function": "api" 
     } 
    ], 
    "public": "public" 
    } 
} 

但是我得到了同樣的問題,函數永遠不會被調用。 我讀過如何重寫最後的手段選項,如果有文件存在於主機,它不會去指定的功能。(我試圖尋找這個ws提到的SO帖子,但我找不到它)所以我從主機的公共目錄中刪除了404.html和index.html文件,因爲我不需要它們。但問題依然存在。

編輯2: 好了,大量的試驗和錯誤之後,我不得不硬編碼的路徑採用以下格式:

rewrites : [ 
     { 
     "source": "https://stackoverflow.com/users/**/**/json", 
     "function": "api" 
     }, 
     { 
     "source": "/api/users/**/**/json", 
     "function": "api" 
     } 
] 

在此之後,快遞應用程序配置是這樣的:

app.get('/users/:userId/:userData/json', Foo) 

我還是希望如果有人能提出一個更好的方式來做到這一點,而不是在每個人工投入托管重寫所需的URI。

+1

您可以編輯您的問題簡要地展示您的明確程序和https的雲功能方面發揮作用的出口?我需要看看你是如何設置的。 –

+0

@DougStevenson先生,謝謝您的回覆。 我對基於JS的後端相當不熟悉,所以我保留了大部分內容,如firebase-examples所示。 –

+1

你能找到解決方案嗎?我也一直在努力解決這個問題... – Pkmmte

回答

11

什麼似乎是主要問題是這樣的:

{ 
    "source": "/api", 
    "function": "api" 
} 

實際上是重寫https://my-firebase-app.cloudfunctions.net/api/api,而不是像https://my-firebase-app.cloudfunctions.net/api你所期望的。注意重複如何api

我對這個解決方案是創建一個main功能,它承載的所有其他頂級功能:

const functions = require('firebase-functions'); 
const express = require('express'); 
const app = express(); 

app.get('/users/:userId/:userData/json', (req, res) => { 
    // Do App stuff here 
} 
// A couple more app.get in the same format 

// Create "main" function to host all other top-level functions 
const main = express(); 
main.use('/api', app); 

exports.main = functions.https.onRequest(main); 

現在,您可以使用此main功能委託給其他所有功能,不破壞你的URL結構:

{ 
    "source": "/api/**", // "**" ensures we include paths such as "/api/users/:userId" 
    "function": "main" 
} 

瞧!您現在可以通過https://my-app.firebaseapp.com/api/users/:userId/:userData訪問所有api函數調用,就像您期望的那樣。

調用此端點,現在重寫爲https://my-firebase-app.cloudfunctions.net/main/api,這在技術上是正確的。然後,您可以通過簡單地將它們添加到您的main功能,如果你想添加更多的頂級功能:

const hooks = express(); 
main.use('/hooks/, hooks); 
+0

在我的情況下,我把所有東西都重定向到'main'函數,所以我再也不需要觸摸firebase.json:''source「:」**「' – Pkmmte

+0

謝謝!這很好用! –

+0

@Pkmmte我不明白爲什麼 { 「源」: 「/ API」, 「功能」: 「API」 }導致重複的URL –

0

您可以使用託管重寫規則的單個火力地堡與Express中一個補充重寫中間件。

  1. firebase.json文件添加rewrite

    { 
        "source": "/api/**", 
        "function": "api" 
    } 
    
  2. 包括app.use()中間件重寫請求URL。

    const functions = require('firebase-functions'); 
    const express = require('express'); 
    
    const API_PREFIX = 'api'; 
    const app = express(); 
    
    // Rewrite Firebase hosting requests: /api/:path => /:path 
    app.use((req, res, next) => { 
        if (req.url.indexOf(`/${API_PREFIX}/`) === 0) { 
         req.url = req.url.substring(API_PREFIX.length + 1); 
        } 
        next(); 
    }); 
    
    app.get('/users/:userId/:userData/json', (req, res) => { 
        // Do App stuff here 
    }); 
    
    exports[API_PREFIX] = functions.https.onRequest(app);