2016-06-09 11 views
5

Pracuję nad API Multi-Environment opartym na frameworku Express. Chcę, aby moja konfiguracja była dynamiczna, np. Ta aplikacja może obsługiwać zarówno aplikacje mobilne, jak i aplikacje internetowe. Jeśli żądanie pochodzi ze źródła mobilnego, należy dołączyć wartość config-app-1.json, w przeciwnym razie config-app-2.json.Multi environment Express Api

Obecnie mam config-app-1.json, config-app-2.json, config-db-1.json, config-db-2.json i configManager.js klasę która określa wymaganą konfigurację w app.listen(). W innych modułach aplikacji wymagam configManager i używam niezbędnych konfiguracji. Prowadzi to jednak do problemu powielania kodu w poszczególnych funkcjach. Każda funkcja musi uzyskać odniesienie do bazy danych i ustawień aplikacji w swoim zasięgu lokalnym.

Chciałbym wiedzieć, jakie są najlepsze praktyki dotyczące budowania API opartego na wielu środowiskach przy użyciu frameworka Express.

+1

Czy możesz dodać fragmenty kodu, które mogą wyjaśnić twój problem . –

Odpowiedz

1

To są pliki konfiguracyjne, oto moje podejście.

Struktura plików

. 
├── app.js 
├── _configs 
| ├── configManager.js 
| ├── database.js 
| └── platform 
|  ├── mobile.js 
|  └── desktop.js 

pliki Środowisko Configs

Configration js są moduły dla każdego urządzenia, a następnie ConfigManager obsługuje których jeden jest aktywny na podstawie urządzenia.

//mobile.js example 
module.exports = { 
    device: 'mobile', 
    configVar: 3000, 
    urls: { 
     base: 'DEVICE_SPECIFIC_BASE_URL', 
     api: 'DEVICE_SPECIFIC_BASE_URL' 
    }, 
    mixpanelKey: 'DEVICE_SPECIFIC_BASE_URL', 
    apiKey: "DEVICE_SPECIFIC_BASE_URL", 
} 

Database Config

konfiguracje baza danych powinna być scentralizowana.

Zazwyczaj można połączyć się z wieloma bazami danych w tej samej instancji węzła, jednak nie jest to zalecane. jeśli koniecznie musisz, po prostu użyj dwóch obiektów (zamiast "mongodb" zamień na "mobileMongoDb" i "desktopMongoDb"), ale polecam użyć jednej bazy danych i podzielić ją na dwa główne dokumenty lub użyć określonych prefiksów ustawionych w twojej platformie specyficzne konfiguracje.

// databse.js example 
module.exports= { 
    mongodb: { 
    host  : 'localhost', 
    port  : 27017, 
    user  : '', 
    password : '', 
    database : 'DB_NAME' 
    }, 
} 

configManager.js (oddanie rzeczy razem)

Jest to prosty plik tylko do demonstracji ..

var userAgent = req.headers['User-Agent']; 
var isMobile = /Mobile|Android|/i.test(userAgent); 



// require them all to be cached when you run node. 
var configs = { 
    mobile: require('./platform/mobile'), 
    desktop: require('./platform/desktop') 
} 
var activeConfig = isMobile? configs.mobile : configs.desktop; 
var dbConfigs = require('./databse'); 


var mongoose = require('mongoose'); 
var express = require('express'); 
var app = express(); 

app.get('/', function (req, res) { 
    var finalresp = 'Hello from '; 
    finalresp += isMobile? 'mobile' : 'desktop; 
    finalresp += activeConfig.configVar; 
    res.send(finalresp); 
}); 

mongoose.connect(dbConfigs.mongodb.host, function(err) { 
    if(isMobile) { /* ... */ } 
}); 

Detect mobilnych od nagłówka

czytaj więcej tutaj https://gist.github.com/dalethedeveloper/1503252

1

Można ustawić zmienne środowiskowe. Zazwyczaj mam wiele plików konfiguracyjnych, o których wspomniałeś.

Następnie ustaw zmienną środowiskową NODE_ENV na lokalną, rozwojową i produkcyjną odpowiednio jako "LOKALNA", "ROZWÓJ" i "PRODUKCJA".

Następnie można skierować środowiska poprzez następujący kod

ENV = process.env.NODE_ENV 
if(ENV === 'PRODUCTION') { 
    mainConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/main-production.json'))) 
    dbConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/db-production.json'))) 

} else if(ENV === 'DEVELOPMENT') { 
    mainConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/main-development.json'))) 
    dbConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/db-development.json'))) 
} else if(ENV === 'LOCAL') { 
    mainConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/main-local.json'))) 
    dbConf = JSON.parse(fs.readFileSync(path.join(__dirname, '/config/db-local.json'))) 
} 

Upewnij się, że prawidłowo ustawić zmienne środowiskowe na środowisko każdego serwera. Użyj pliku konfiguracyjnego json pobranego z powyższego kodu, tak jak chcesz.

+0

To przyniesie działanie w moim przypadku, zmienne środowiskowe nie mogą się zmienić w czasie wykonywania. To, czego szukam, to zmienić konfigurację na podstawie parametrów żądania. –

1

Czy źródło żądania (np. Telefon komórkowy - sieć) może się zmienić w czasie wykonywania? Innymi słowy, może zażądać 1 pochodzić z urządzenia mobilnego i poprosić 2 z sieci?

Jeśli tak, możesz przyjrzeć się agentowi użytkownika w nagłówkach, aby określić rodzaj urządzenia, z którym masz do czynienia. To jednak powoduje, że jesteś zależny od agenta użytkownika, a jeśli nie zostanie wysłany, nie będziesz mógł zidentyfikować swojego klienta.

req.headers['User-Agent'];

Jeśli jesteś właścicielem klientów siebie, można dodać obiekt do każdego wniosku, powiedzmy dodatkowy nagłówek. req.headers['X-Client-Type'] = 'Mobile'; //Web.

W ten sposób nie jesteś zależny od agenta użytkownika i wciąż możesz zidentyfikować typ każdego klienta.

Wreszcie, jeśli masz do czynienia z klientami stron trzecich, innymi osobami, które tworzą aplikacje do trafienia w Twój interfejs API, możesz chcieć, aby rejestrowały swoje aplikacje. (Imię i nazwisko, nazwa programisty, dane kontaktowe, może zgodzić się na jakiś rodzaj umowy o świadczenie usług, a także podać rodzaj klienta, sieć kontra telefon komórkowy).

Będziesz wtedy mógł pobrać typ każdego klienta na każde nowe żądanie.