Denne manualen viser hvordan du bygger en liten, praktisk web-løsning i Norscode. Målet er ikke bare å få en server til å svare, men å bygge noe som er lett å lese, lett å teste og enkelt å videreutvikle når prosjektet vokser.
For mange prosjekter er web-laget stedet der flere hensyn møtes samtidig: routing, validering, HTML, JSON, statuskoder og dokumentasjon. Derfor er det nyttig å se disse delene som ett samlet arbeidsmønster i stedet for som mange små teknikker hver for seg.
Oppsettet under bygger en liten løsning i fire faser:
Handler-funksjonen er inngangsporten til web-laget. Det er her requesten først blir tolket, og det er her du bestemmer om kallet skal svare med HTML, JSON, feil eller en annen responsform.
Norscode mottar standardparametere i web-handleren:
method – HTTP-metode (GET/POST)path – pathen som er kaltquery – rå query stringbody – request body som tekstbruk std.web som web
funksjon hjem_handler(method: tekst, path: tekst, query: tekst, body: tekst) -> tekst {
hvis method != "GET" da {
returner web.http_respons_tekst(405, web.http_content_type_json(), "{\"error\":\"Metode ikke tillatt\"}")
}
returner web.http_respons_tekst(
200,
"text/html; charset=utf-8",
"<h1>Norscode</h1><p>API klart.</p>"
)
}
Dette enkle mønsteret er nyttig fordi det holder ansvaret tydelig. Handleren vet hvilken metode som er lov, og returnerer en eksplisitt respons. Det gjør koden lettere å teste og lettere å lese senere, både for deg selv og andre.
Bruk http_json_respons for strukturert API-svar. Når du holder JSON-svarene enkle og konsekvente, blir de lettere å bruke fra frontend, lettere å dokumentere og lettere å verifisere i tester.
funksjon status_handler(method: tekst, path: tekst, query: tekst, body: tekst) -> tekst {
hvis method != "GET" da {
returner web.http_respons_tekst(405, web.http_content_type_json(), "{\"error\":\"Kun GET tillatt\"}")
}
returner web.http_json_respons("{\"ok\":true,\"service\":\"norscode\",\"version\":\"1.0.0\"}")
}
Selv et lite status-endepunkt er nyttig som mønster. Det lærer deg å skille mellom en HTML-side for mennesker og et JSON-svar for systemer. Den skillen blir bare viktigere jo flere ruter og klienter løsningen får.
Her begynner web-laget å bli mer realistisk. Når du tar imot data, må du ikke bare lese bodyen, men også definere hva som er gyldig, hva som skal avvises og hvordan feilsvaret bør se ut.
Eksempel på POST med JSON-felt og enkel validering:
funksjon kontakt_handler(method: tekst, path: tekst, query: tekst, body: tekst) -> tekst {
hvis method != "POST" da {
returner web.http_respons_tekst(405, web.http_content_type_json(), "{\"error\":\"Kun POST tillatt\"}")
}
la navn: tekst = web.http_body_json_felt_tekst(body, "navn")
hvis navn == "" da {
returner web.http_typed_input_feil_respons("body", "navn", "ikke tom", navn)
}
returner web.http_json_respons("{\"mottatt\":\"" + navn + "\"}")
}
Det viktigste her er ikke bare å lese feltet, men å etablere forventningene tydelig. Når ugyldig input behandles bevisst og forutsigbart, blir hele API-et enklere å stole på og enklere å dokumentere.
Når API-et har en kontrakt, slipper du å holde manuell dokumentasjon løsrevet fra koden. OpenAPI gjør det enklere å vise hvilke ruter som finnes, hva de gjør og hvilke svar som kan forventes.
funksjon kontakt_openapi() -> tekst {
la api: liste_tekst = web.openapi_tom()
web.openapi_info_registrer(api, "title", "Norscode Kontakt")
web.openapi_info_registrer(api, "version", "1.0.0")
web.openapi_info_registrer(api, "description", "Enkel kontakt- og status-API")
web.openapi_rute_registrer(api, "GET", "/api/status", "Hent status", "Returnerer tjenestestatus", "status", "StatusResponse")
web.openapi_rute_registrer(api, "POST", "/api/kontakt", "Opprett henvendelse", "Tar i mot navn som body", "kontakt", "KontaktResponse")
returner web.openapi_json(api)
}
Dette er særlig nyttig når API-et skal brukes av andre enn bare deg selv. En eksplisitt kontrakt reduserer misforståelser og gjør endringer lettere å oppdage i tide.
Serveren trenger en tabell over METHOD\tPATH\tHANDLER. Dette gjør rutene eksplisitte i stedet for magiske, og det gir deg ett tydelig sted å lese hvordan web-laget faktisk er satt sammen.
funksjon ruter() -> liste_tekst {
returner [
"GET\t/\t__main__.hjem_handler",
"GET\t/api/status\t__main__.status_handler",
"POST\t/api/kontakt\t__main__.kontakt_handler",
"GET\t/api/openapi\t__main__.kontakt_openapi"
]
}
funksjon start() -> heltall {
returner web.web_server_start(ruter(), "127.0.0.1", 8080)
}
Når ruteoppsettet holdes ryddig, blir det også lettere å teste at viktige endepunkter fortsatt finnes og å oppdage når en rute mangler etter en refaktorering.
Bruk denne rekkefølgen i egne prosjekter:
Poenget med denne rekkefølgen er at du bygger web-laget uten å hoppe mellom for mange nivåer samtidig. Først bestemmer du data og ansvar, så bygger du rutene, deretter kontrakten og til slutt sikkerhetsnettet rundt det hele.
Webkode blir mer robust når du tester handlerne direkte, i stedet for å vente til hele systemet er koblet sammen. Da er det enklere å verifisere både responsform, kontrakter og valideringsregler tidlig.
test "API-svar er gyldig" {
la status: tekst = status_handler("GET", "/api/status", "", "")
assert(tekst_inneholder(status, "\"ok\":true"))
la openapi: tekst = kontakt_openapi()
assert(tekst_inneholder(openapi, "\"/api/status\""))
assert(tekst_inneholder(openapi, "\"/api/kontakt\""))
}
Denne typen test er spesielt nyttig fordi den dekker mer enn bare én funksjon. Den bekrefter også at dokumentasjon og ruteoppsett fortsatt peker i samme retning.
content_type for HTML vs JSONEn annen vanlig feil er å blande domenelogikk og web-responsbygging for tett. Da blir det vanskeligere å teste hver del for seg, og handlerne ender ofte opp med å eie mer ansvar enn de burde.
Før produksjon er det også lurt å spørre om web-laget er lett å lese for en annen utvikler. Hvis ruter, statuskoder og validering er tydelige, blir systemet enklere å drifte og enklere å feilsøke når noe faktisk går galt.
Gå videre til Eksempelsamlingen for komplette kodesnutter du kan lime rett inn i egne filer. Det er også naturlig å koble dette videre til testing og moduler, siden webkode blir sterkes