1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- #
- # Copyright (c) 2023 supercell
- #
- # SPDX-License-Identifier: BSD-3-Clause
- #
- # This is an example HTTP server which
- # accepts a Markdown request and returns
- # the parsed HTML.
- require "ecr"
- require "http"
- require "log"
- require "./default_markdown"
- require "../src/luce.cr"
- PORT = ENV.fetch("LUCE_PORT", "8080").to_i32
- def serve_index(response : HTTP::Server::Response, params : URI::Params) : Nil
- response.status_code = 200
- response.content_type = "text/html"
- markdown = params.fetch("markdown", DEFAULT_MARKDOWN)
- extension_set = params.fetch("extension", "CommonMark")
- es = case extension_set
- when "CommonMark"
- Luce::ExtensionSet::COMMON_MARK
- when "GitHub"
- Luce::ExtensionSet::GITHUB_WEB
- else
- Luce::ExtensionSet::NONE
- end
- # `ren_markdown` is used in "index.ecr"
- # ameba:disable Lint/UselessAssign
- ren_markdown = Luce.to_html(markdown, extension_set: es)
- renderer = ECR.render "index.ecr"
- bytes = renderer.unsafe_byte_slice(0)
- response.content_length = bytes.size
- response.write(bytes)
- end
- def method_not_allowed(response : HTTP::Server::Response) : Nil
- response.headers["Allow"] = "GET"
- response.respond_with_status(405)
- end
- DEFAULT_PARAMS = URI::Params.new({"markdown" => [DEFAULT_MARKDOWN], "extension" => ["CommonMark"]})
- def process_request(request : HTTP::Request) : URI::Params
- return DEFAULT_PARAMS if request.body.nil?
- body = request.body.not_nil!
- form = body.gets_to_end
- URI::Params.parse(form)
- end
- def plain(response : HTTP::Server::Response, resource : String) : Nil
- css = File.read(".#{resource}")
- response.status_code = 200
- css_bytes = css.unsafe_byte_slice(0)
- response.content_length = css_bytes.size
- response.write(css_bytes)
- end
- server = HTTP::Server.new do |context|
- # Probably not the best way to do this.
- case context.request.resource
- when "/preview"
- if context.request.method == "POST"
- params = process_request(context.request)
- serve_index(context.response, params)
- else
- method_not_allowed(context.response)
- end
- when "/", "/index.html"
- serve_index(context.response, DEFAULT_PARAMS)
- when /.*\.css/, /.*\.js/
- plain(context.response, context.request.resource)
- when /favicon/
- # There are probably other requests that should
- # just be ignored, but this is just an example.
- context.response.respond_with_status(404)
- else
- context.response.status_code = 301
- context.response.headers["Location"] = "/index.html"
- end
- # makes this example look official ;p
- Log.info { "#{context.request.method}: #{context.response.status_code} #{context.request.resource}" }
- end
- address = server.bind_tcp(PORT)
- puts "Running Crystal #{Crystal::VERSION}"
- puts "Listening on http://#{address}"
- server.listen
|