Maak kennis met het Connect Framework

Nieuwkomers bij NodeJS vinden de API meestal moeilijk te begrijpen. Gelukkig hebben veel ontwikkelaars frameworks gemaakt die het gemakkelijker maken om met Node te werken. Connect is zo'n kader. Het zit bovenop de API van Node en tekent de grens tussen comfort en controle.

Zie Connect als een stapel middleware. Bij elk verzoek filtert Connect via de lagen van de middleware, die elk de mogelijkheid hebben om het HTTP-verzoek te verwerken. Wanneer T.J. Holowaychuk heeft Connect aangekondigd, hij zei dat er twee soorten middleware waren. De eerste is a filter.

Filters verwerken de aanvraag, maar ze reageren er niet op (denk aan server logging).

Het andere type is a leverancier, die op het verzoek reageert. Je kunt zoveel lagen middleware opnemen als je wilt; het verzoek gaat door elke laag totdat een van de middleware reageert op het verzoek.


Basis syntaxis

Eerst moet u het Connect-pakket via npm installeren:

npm install connect

Maak nu een server.js bestand en voeg de volgende code toe:

var connect = require ("connect");

De aansluiten variabele is een functie die een nieuwe Connect-toepassing retourneert. Dus onze volgende stap is om die app te maken:

var app = connect ();

U hoeft geen app variabele voor de meeste van uw toepassingen. De functies die betrokken zijn bij het maken van een applicatie (aansluiten() en gebruik()) zijn ketenbaar:

connect () .use (/ * middleware * /) .use (/ * middleware * /) .listen (3000);

De gebruik() functie voegt een laag middleware toe aan de applicatie en de luister() functie vertelt onze applicatie om te beginnen met het accepteren van verbindingen op de opgegeven poort (3000 in dit voorbeeld).

Laten we beginnen met iets eenvoudigs: loggen. De code voor een Connect-toepassing die alleen de logging-middleware gebruikt, is vrij eenvoudig:

connect () .use (connect.logger ()) .listen (3000);

Standaard parseert het knooppunt zeer weinig van het binnenkomende verzoek.

Voeg die code toe aan uw bestand en start de server door te draaien knooppunt server.js. Navigeer naar een willekeurig pad in uw browser en negeer de resultaten "Can not GET ...". We zijn niet geïnteresseerd in wat de server terug naar de browser heeft gestuurd; we zijn geïnteresseerd in het log van de server. Kijk naar de terminal en je ziet het logboek van je verzoeken. Raadpleeg de documentatie bij de logger voor informatie over andere functies en aanpassingen.

Dat was een filter; laten we nu naar een provider kijken. De eenvoudigste provider is de statische provider; het dient statische bestanden van een bepaalde map. Hier is de syntaxis:

.gebruik (connect.static (__ dirname + "/ public")

U kunt waarschijnlijk het doel van Node's raden __dirname variabele: het is het pad naar de huidige map. Deze middleware dient statisch alles van een openbaar map in de huidige map. Dus maak public / pagina.html en voeg een toe

element. Start de server opnieuw op (knooppunt server.js) en navigeer naar localhost: 3000 / pagina.html in uw browser. Je zou moeten pagina.html weergegeven in de browser.

Laten we nu een korte blik werpen op enkele van de andere middleware-opties van Connect.


Verzoekende instanties uitvragen

Standaard parseert Knoop heel weinig van het binnenkomende verzoek, maar je kunt verschillende filters opnemen om het verzoek te ontleden als je meer complexiteit moet behandelen. Er zijn vier filters:

  • connect.json () analyseert JSON-aanvraaglichamen (waarbij de inhoudstype is application / json).
  • connect.urlencoded () ontleedt x-ww-vorm urlencoded organen.
  • connect.multipart () ontleedt multipart / form-data organen.
  • connect.bodyParser () is een snelkoppeling voor het inschakelen van alle bovenstaande drie.

Het gebruik van een van deze filters geeft je de mogelijkheid om je geparseerde instantie via te benaderen request.body (we zullen praten over hoe je dat kunt krijgen verzoek object binnenkort).

Ik denk dat deze filters een goed voorbeeld zijn van hoe je je controle kunt verfijnen met Connect. U kunt heel weinig verwerken om uw toepassing te stroomlijnen.


Cookies en sessies parseren

Cookies en sessies vormen een belangrijk onderdeel van elke webtoepassing en er zijn verschillende soorten middleware die u helpen deze te beheren. De connect.cookieParser () parseert cookies voor u en u kunt de cookies en hun waarden ophalen via de Request.Cookies voorwerp. Dit is handiger als u de connect.session () filter naar uw app. Dit filter vereist dat de cookie-parser al op zijn plaats zit. Hier is een klein voorbeeld:

connect () .use (connect.cookieParser ()) .use (connect.session (secret: 'some secret text', cookie: maxAge: 30000)) .use (function (req, res) var sessies = req.session, url = req.url.split ("/"); if (url [1] == "naam" && url [2]) sess.name = url [2]; res.end (" naam opgeslagen: "+ url [2]); else if (sess.name) res.write (" session-stored name: "+ sess.name); res.end (" stored for another: "+ (sess .cookie.maxAge / 1000) + "seconden"); else res.end ("geen opgeslagen naam; ga naar / naam / naam om een ​​naam op te slaan");). listen (3000);

Elke middleware-functie die u schrijft, moet het verzoek doorgeven aan de volgende laag of reageer op het verzoek.

Na de cookieParser, we nemen de sessie filter en geef het een twee opties:

  • De geheim maakt een ondertekende cookie die de sessie bijhoudt.
  • De cookie.maxAge definieert zijn levensduur in milliseconden; de 30000 in deze code is 30 seconden.

In de finale gebruik() bellen, we geven een functie door die reageert op het verzoek. We gebruiken twee eigenschappen van de verzoek voorwerp: req.session voor sessiegegevens, en req.url voor de aanvraag-URL.

Als de applicatie een verzoek ontvangt voor / Naam / some_name, dan slaat het de waarde op some_name in req.session.name. Alles wat in een sessie is opgeslagen, kan worden opgehaald in volgende aanvragen voor de duur van onze sessie. Alle verzoeken zijn gedaan voor / Naam / andere vervangt de sessievariabele en aanvragen naar andere URL's voeren de waarde van de sessie-variabele en de resterende tijd voor de sessie uit.

U kunt dus naar navigeren localhost: 3000 / naam / your_name, en ga dan naar localhost: 3000 zien uw naam. Ververs de pagina een paar keer en kijk hoe de seconden aftellen. Wanneer de sessie verloopt, ziet u het standaardbericht "no stored name".

Ik noemde dat de cookieParser filter moet eerder komen sessie.

De volgorde van opname is belangrijk met middleware omdat het verzoek op volgorde van laag naar laag wordt doorgegeven.

Omdat sessie heeft de geparseerde cookiegegevens nodig, het verzoek moet doorstaan cookieParser voor sessie.

Ik zou elk ander ingebouwd stukje middleware kunnen uitleggen, maar ik zal er nog een paar noemen voordat we onze eigen code schrijven om te communiceren met Connect.

  • comprimeren: Gzip-compressie-middleware
  • basicAuth: standaard http-authenticatie
  • map: directory lijst middleware
  • errorHandler: flexibele foutafhandelaar

Je eigen middleware schrijven

U hebt net geleerd hoe u uw eigen code schrijft met Connect. Hier is de basissyntaxis nogmaals:

.gebruik (functie (req, res, next) )

De drie parameters van de functie zijn belangrijk; ze bieden toegang tot de buitenwereld. De req parameter is natuurlijk het verzoekobject, en res is het antwoord. De derde parameter, volgende, is de sleutel tot het maken van functies die goed werken in de middleware-stack. Het is een functie die het verzoek doorgeeft aan de volgende middleware in de stapel. Zie dit voorbeeld:

connect () .use (functie (req, res, next) if (req.method === 'POST') res.end ("Dit is een POST-aanvraag"); else next (); ) .use (functie (req, res) res.end ("Dit is geen POST-verzoek (waarschijnlijk een GET-verzoek)");). listen (3000);

Deze code gebruikt twee middleware-functies. De eerste functie controleert de aanvraagmethode om te zien of het een POST-aanvraag is. Als dat zo is, reageert het door dat te zeggen. Anders bellen we next () en geef het verzoek door aan de volgende functie, die ongeacht wat reageert. Gebruik Krul om beide lagen in de terminal te testen:

$ curl http: // localhost: 3000 Dit is geen POST-verzoek (waarschijnlijk een GET-verzoek) $ curl -X POST http: // localhost: 3000 Dit is een POST-aanvraag

Als je de terminal niet leuk vindt, probeer dan deze handige Chrome-plug-in.

Het is belangrijk om te onthouden dat elke middleware-functie die u schrijft, het verzoek moet doorgeven aan de volgende laag of reageer op het verzoek. Als uw functie vertakt (via if-statements of andere conditionals), moet u ervoor zorgen dat elke branch de aanvraag doorstaat of erop reageert. Als uw app in de browser hangt, komt dit waarschijnlijk omdat u bent vergeten te bellen next () op een gegeven moment.

Nu, hoe zit het met die verzoek en antwoord parameters? Dit zijn dezelfde request- en response-objecten die u ontvangt bij het gebruik van een "raw" Node-server:

vereisen ("http"). createServer (functie (req, res) // ...). listen (3000);

Als je de server-API van Node nog niet eerder hebt gebruikt, wil ik je laten zien wat je ermee kunt doen.


Het verzoekobject

De verzoek object is eigenlijk een http.IncomingMessage object en de belangrijke eigenschappen worden hieronder weergegeven:

  • req.method vertelt u welke HTTP-methode werd gebruikt.
  • req.url vertelt u welke URL is aangevraagd.
  • req.headers is een object met de headernamen en -waarden.
  • req.query is een object met alle gegevens in een querytekenreeks (om dat te analyseren, hebt u de connect.query () middleware op zijn plaats).
  • req.body is een object van de formuliergegevens (je hebt bepaalde body parsing middleware nodig).
  • req.cookies is een object van de cookiegegevens (vereist cookie-parsing).
  • req.session is een object van de sessiegegevens (nogmaals, u zult cookie-parsing en sessie-middleware op zijn plaats nodig hebben)

Je kunt dit allemaal aan het werk zien met de volgende code:

connect () .use (connect.query ()) // geeft ons req.query .use (connect.bodyParser ()) // geeft ons req.body .use (connect.cookieParser ()) // voor sessie .use (connect.session (secret: "asdf")) // geeft ons req.session .use (function (req, res) res.write ("req.url:" + req.url + "\ n \ n "); res.write (" req.method: "+ req.method +" \ n \ n "); res.write (" req.headers: "+ JSON.stringify (req.headers) +" \ n \ n "); res.write (" req.query: "+ JSON.stringify (req.query) +" \ n \ n "); res.write (" req.body: "+ JSON.stringify (req. body) + "\ n \ n"); res.write ("req.cookies:" + JSON.stringify (req.cookies) + "\ n \ n"); res.write ("req.session:" + JSON.stringify (req.session)); res.end ();). Listen (3000);

Als u iets wilt zien voor elk van deze waarden, moet u enkele gegevens posten naar een URL met een queryreeks. Het volgende zou voldoende moeten zijn:

curl -X POST -d "name = YourName" "http: // localhost: 3000 / some / url? some = data"

Met deze zeven eigenschappen kunt u vrijwel elk verzoek beheren dat u ontvangt. Ik denk niet dat trailers vaak worden gebruikt (ik heb ze nog nooit in mijn ervaring gezien), maar je kunt ze gebruiken req.trailers als je ze verwacht in je vragen (trailers zijn net als headers, maar na het lichaam).

Dus, hoe zit het met je reactie?


Het antwoordobject

Het onbewerkte antwoordobject biedt niet de luxe die bibliotheken (zoals Express) u bieden. U kunt bijvoorbeeld niet reageren met een eenvoudige render-oproep naar een premadesjabloon - althans, niet standaard. Er wordt heel weinig verondersteld in het antwoord, dus je moet alle kleine details invullen.

We beginnen met de statuscode en de antwoordheaders. U kunt deze allemaal tegelijk instellen met behulp van de writeHead () methode. Hier is een voorbeeld uit de Node-documenten:

var body = 'hallo wereld'; response.writeHead (200, 'Content-Length': body.length, 'Content-Type': 'text / plain');

Als u afzonderlijke headers moet instellen, kunt u de setHeader () methode:

connect () .use (functie (req, res) var accept = req.headers.accept.split (","), body, type; console.log (accept); if (accept.indexOf ("application / json ")> -1) type =" application / json "; body = JSON.stringify (message:" hello "); else if (accept.indexOf (" text / html ")> -1) type = "text / html"; body = "

Hallo!

"; else type =" text / plain "; body =" hallo! "; res.statusCode = 200; res.setHeader (" Inhoudstype ", type); res.end (hoofdtekst);). listen (3000);

Voeg deze code toe aan een bestand, start de server op en vraag het aan in de browser. Je hebt HTML! Nu uitvoeren:

krul http: // localhost: 3000

En je ontvangt platte tekst. Probeer dit voor JSON:

krul -H "accepteren: application / json" http: // localhost: 3000

Allemaal van dezelfde URL!

Gebruik res.getHeader (naam) als je wilt weten welke koppen al zijn ingesteld. Je kunt ook gebruiken res.removeHeader (naam) om een ​​koptekst te verwijderen.

Natuurlijk is een reactie nutteloos zonder een lichaam. Zoals je in deze tutorial hebt gezien, kun je stukjes data naar de body schrijven met de res.write () methode. Hiermee accepteert u een tekenreeks- of bufferobject als argument. Als het een tekenreeks is, is de tweede parameter het coderingstype (standaard is dit de parameter utf8).

De opnieuw versturen() methode sluit de body, maar u kunt er gegevens aan doorgeven om naar de reactiestream te schrijven. Dit is handig in situaties waar u slechts één regel hoeft uit te voeren.


Middleware van derden

Het is enigszins moeilijk om te reageren met grotere HTML-lichamen in gewoon oud knooppunt en Connect. Dit is een goede plek om middleware van derden in de mix te gooien. U kunt een lijst met middleware van derden vinden op de Connect Github-wiki. We gaan bijvoorbeeld het Connect-Jade-pakket gebruiken, waarmee we jade-weergaven kunnen weergeven.

Installeer eerst connect-jade:

npm install connect-jade

Vereisen en vervolgens toevoegen als middleware. U wilt een paar standaardwaarden instellen:

var connect = require ("connect"), connectJade = require ("connect-jade"); connect () .use (connectJade (root: __dirname + "/ views", standaard: title: "MyApp")) .use (function (req, res) res.render ("index", heading : "Welcome to My App");). Listen (3000);

Stel de root in als de map die de weergavebestanden bevat. Je kunt ook instellen defaults; dit zijn variabelen die beschikbaar zijn in elke weergave, tenzij we ze later opheffen tijdens het bellen render ().

De laatste functie in deze code belt naar res.render (). Deze methode wordt geleverd door de connect-jade pakket.

Het eerste argument dat wordt geaccepteerd, is de naam van de weergave die moet worden weergegeven.

Het is het pad naar het uitzicht, zonder het pad dat we hebben gedefinieerd bij het toevoegen van de middleware, zonder de jade bestandsextensie. Voor deze code hebben we een views / index.jade sjabloon om te renderen. We houden het simpel:

html head title = title body h1 = heading

Als u niet bekend bent met jade, markeren we tagnamen om een ​​HTML-structuur te maken. Het gelijkteken haalt de waarde van een JavaScript-variabele op. Die variabelen komen uit de defaults we ingesteld, plus het (optionele) tweede parameterobject doorgegeven aan res.render ().

Er zijn veel andere middlewares van derden, maar ze werken op elkaar. Je installeert ze via npm, vereist ze en zet ze in actie.


Modules als middleware

Als je je verdiept in hoe Connect werkt, zul je zien dat elke laag eigenlijk een knooppuntmodule is - een heel intelligent ontwerp. Als u Connect voor omvangrijke applicaties gebruikt, zou het ideaal zijn om uw code in de module-indeling van de Node te schrijven. Je hebt misschien een app.js bestand als dit:

// app.js module.exports = functie (req, res, next) res.end ("dit komt uit een module"); ;

En in jouw server.js:

var connect = require ("connect"), app = require ("./ app"); connect () .use (app) .listen (3000);

Conclusie

Als u een beginner-vriendelijke bibliotheek wilt waarmee u gemakkelijk grote web-apps kunt bouwen, dan is Connect niet uw oplossing. Connect is bedoeld als een dunne laag bovenop de onbewerkte knooppunt-API die u volledige controle geeft over uw servertoepassing. Als je wat meer wilt, raad ik Express aan (overigens door dezelfde mensen). Anders is Connect een fantastische, uitbreidbare bibliotheek voor Node-webtoepassingen.