모든 스타일을 지배하는 하나의 Nim 웹 프레임워크

19329 단어 webdevnim

소개



Nim 언어는 우아하고 표현력이 풍부한 프로그래밍 언어입니다. 강력한 매크로 시스템을 통해 인상적인 프로그램을 만들 수 있습니다. 님 세계의 마법을 가지고 놀자.

요구 사항



님 버전 >= 1.4.0 Installation
Prologue 버전 >= 0.4.0

nimble install [email protected]


배경



Prologue은 Nim 세계의 훌륭한 웹 프레임워크입니다. 그러나 Prologue 프레임워크는 macros 를 사용하지 않으려고 합니다. reduce magic and reduce surprise . 매크로는 중복 코드베이스로부터 당신을 구할 수 있습니다. 한편으로는 놀라움을 선사할 수도 있습니다. 이 문서에서는 웹 프레임워크 내부를 침범하지 않고 라우팅 스타일을 외부로 확장하는 방법Prologue에 대해 설명합니다.
Prologue를 사용하여 기본적으로 라우팅을 등록하는 세 가지 방법이 있습니다.

콜백을 사용하는 것이 가장 기본적인 방법입니다. 먼저 "Hello World!"에 응답하는 비동기 함수를 작성합니다. 클라이언트에게. 다음으로 새Prologue 인스턴스를 만듭니다. 그런 다음 get 함수를 사용하여 라우팅 및 핸들러를 등록합니다. 마지막으로 run 응용 프로그램입니다.

방문 localhost:8080/hello 및 "Hello World!"화면에 표시됩니다.

import prologue
proc hello(ctx: Context) {.async.} =
  resp "Hello World!"
var app = newApp()
app.get("/hello", hello)
app.run()

Express.js 또는 Koa 웹 프레임워크를 좋아한다면 익명 기능을 사용하는 아래 스타일을 선호할 수 있습니다.

방문 localhost:8080/hello 및 "Hello World!"화면에 표시됩니다.

import prologue
var app = newApp()
app.get("/hello", proc(ctx: Context) {.async.} =
  resp "Hello World!")
app.run()

Django 웹 프레임워크를 좋아한다면 URL 패턴을 사용하는 아래 스타일을 선호할 수 있습니다.

방문 localhost:8080/hello 및 "Hello World!"화면에 표시됩니다.

import prologue
proc hello(ctx: Context) {.async.} =
  resp "Hello World!"
let urlPatterns = @[
  pattern("/hello", hello)
]
var app = newApp()
app.addRoute(urlPatterns, "")
app.run()


마술



오늘의 주제는 웹 프레임워크 외부의 강력한 매크로로 확장Prologue하는 것입니다.

웹 프레임워크Flask를 좋아한다면 pragma를 사용하여 데코레이터를 시뮬레이트하는 아래 스타일을 선호할 수 있습니다.

핵심 코드베이스는 단 4줄입니다.

import prologue
import std/macros
macro get*(app: Prologue, path: string, body: untyped) = 
  let handler = body[0] # Gets the name of handler, for example "hello"
  result = quote do:
    prologue.get(`app`, `path`, `handler`)
macro get*(app: Prologue, path: string, middlewares: openArray[HandlerAsync], body: untyped) = discard
var app = newApp()
proc hello(ctx: Context) {.async, get(app, "/hello").} =
  resp "<h1>Hello, Prologue!</h1>"
app.run()

Jester 또는 Sinatra 웹 프레임워크를 좋아한다면 아래 스타일을 선호할 수 있습니다.

핵심 코드베이스도 단 4줄입니다.

import prologue except get
import std/[macros, with]
macro get*(app: Prologue, route: string, body: untyped) =
  let ctx = ident"ctx"
  result = quote do:
    prologue.get(`app`, `route`, proc (`ctx`: Context) {.async.} = `body`)
var app = newApp()
with app:
  get "/hello":
    resp "<h1>Hello, Prologue!</h1>"
app.run()


오토메이션



강력한 매크로 시스템은 Prologue 프레임워크를 DSL 스타일로 완전히 변환할 수 있습니다(@ exelotl 및 @ Vindaar 덕분에). 템플릿을 사용하여 코드베이스를 생성하는 데 사용할 수 있습니다. 중복 코드는 단순화됩니다. 적을수록 좋습니다.

전체 코드베이스는 40줄 미만입니다. defineRouteSugardefineGroup는 모든 DSL 라우팅 함수를 생성하는 템플릿입니다. 코드베이스를 간단하고 잘못하기 어렵게 만듭니다.

# dsl_style.nim
import prologue except head, get, post, put, delete, options
import std/macros
export prologue
macro defineRouteSugar(name: untyped) =
  let ctx = ident"ctx"
  result = quote do:
    template `name`*(app: Prologue, route: string, body: untyped) =
      prologue.`name`(app, route, proc(`ctx`: Context) {.async.} =
                                    let ctx {.inject.} = `ctx`
                                    body)
macro defineGroupSugar(name: untyped) =
  let ctx = ident"ctx"
  result = quote do:
    template `name`*(group: Group, route: string, body: untyped) =
      prologue.`name`(group, route, proc(`ctx`: Context) {.async.} = 
                                      let ctx {.inject.} = `ctx`
                                      body)
defineRouteSugar(head)
defineRouteSugar(get)
defineRouteSugar(post)
defineRouteSugar(put)
defineRouteSugar(delete)
defineRouteSugar(options)
defineGroupSugar(head)
defineGroupSugar(get)
defineGroupSugar(post)
defineGroupSugar(put)
defineGroupSugar(delete)
defineGroupSugar(options)


테스트 코드:

# app.nim
include dsl_style
import std/with
var
  app = newApp()
  base = newGroup(app, "/apiv2", @[])
  level1 = newGroup(app,"/level1", @[], base)
  level2 = newGroup(app, "/level2", @[], level1)
  level3 = newGroup(app, "/level3", @[], level2)
with app:
  get "/":
    resp "<h1>Hello, Prologue!</h1>"
  get "/hello":
    resp "<h1>Hello, Prologue!</h1>"
with base:
  get "/":
    resp "<h1>Hello, Prologue!</h1>"
  post "/":
    resp "<h1>Hello, Prologue!</h1>"
with level3:
  get "/":
    resp "<h1>Hello, Prologue!</h1>"
  get "/hello":
    resp "<h1>Hello, Prologue!</h1>"
app.run()

Prologue에 관심이 있거나 매크로를 기반으로 이러한 플러그인을 유지 관리하려면 당사discord server에 가입하세요.

좋은 웹페이지 즐겨찾기