A response to send over HTTP

Introduced properties

fun body: Writable

nitcorn :: HttpResponse :: body

Body of this response
fun body=(body: Writable)

nitcorn :: HttpResponse :: body=

Body of this response
fun color_status: String

nitcorn :: HttpResponse :: color_status

Return self status colored for console.
fun csv(csv: nullable CsvDocument, status: nullable Int)

nitcorn :: HttpResponse :: csv

Write data as CSV and set the right content type header.
fun error(status: Int)

nitcorn :: HttpResponse :: error

TODO The error message should be parameterizable.
fun files: Array[String]

nitcorn :: HttpResponse :: files

Files appended after body
protected fun files=(files: Array[String])

nitcorn :: HttpResponse :: files=

Files appended after body
fun finalize

nitcorn :: HttpResponse :: finalize

Finalize this response before sending it over HTTP
fun header: HashMap[String, String]

nitcorn :: HttpResponse :: header

Headers of this response as a Map
protected fun header=(header: HashMap[String, String])

nitcorn :: HttpResponse :: header=

Headers of this response as a Map
fun html(html: nullable Writable, status: nullable Int)

nitcorn :: HttpResponse :: html

Write data as HTML and set the right content type header.
fun http_version: String

nitcorn :: HttpResponse :: http_version

HTTP protocol version
fun http_version=(http_version: String)

nitcorn :: HttpResponse :: http_version=

HTTP protocol version
fun json(json: nullable Serializable, status: nullable Int, plain: nullable Bool, pretty: nullable Bool)

nitcorn :: HttpResponse :: json

Write data as JSON and set the right content type header.
fun json_error(message: String, status: Int)

nitcorn :: HttpResponse :: json_error

Write error as JSON.
fun pug(pug_string: nullable String, json: nullable Serializable, status: nullable Int)

nitcorn :: HttpResponse :: pug

Render pug_string with the command cli pug and use data from json
fun pug_file(file: String, json: nullable Serializable, status: nullable Int)

nitcorn :: HttpResponse :: pug_file

Render file with the command cli pug and use data from json
fun redirect(location: String, status: nullable Int)

nitcorn :: HttpResponse :: redirect

Redirect response to location
fun render: Writable

nitcorn :: HttpResponse :: render

Get this reponse as a string according to HTTP protocol
fun send(raw_data: nullable Writable, status: nullable Int)

nitcorn :: HttpResponse :: send

Write data in body response and send it.
fun sent: Bool

nitcorn :: HttpResponse :: sent

Was this request sent by a handler?
protected fun sent=(sent: Bool)

nitcorn :: HttpResponse :: sent=

Was this request sent by a handler?
fun session: nullable Session

nitcorn :: HttpResponse :: session

A Session to associate with a response
fun session=(session: nullable Session)

nitcorn :: HttpResponse :: session=

A Session to associate with a response
fun status_code: Int

nitcorn :: HttpResponse :: status_code

Status code of this response (200, 404, etc.)
fun status_code=(status_code: Int)

nitcorn :: HttpResponse :: status_code=

Status code of this response (200, 404, etc.)
fun status_message: nullable String

nitcorn :: HttpResponse :: status_message

Return the message associated to status_code
fun template(tpl: nullable TemplateString, values: nullable Map[String, nullable Writable], status: nullable Int)

nitcorn :: HttpResponse :: template

Render the TemplateString tpl with values and write it as html.
fun template_file(file: String, values: nullable Map[String, nullable Writable], status: nullable Int)

nitcorn :: HttpResponse :: template_file

Render file as a TemplateString with values and write it as html.
fun template_string(tpl_string: nullable String, values: nullable Map[String, nullable Writable], status: nullable Int)

nitcorn :: HttpResponse :: template_string

Render file as a TemplateString with values and write it as html.

Redefined properties

redef type SELF: HttpResponse

nitcorn $ HttpResponse :: SELF

Type of this instance, automatically specialized in every class
redef fun core_serialize_to(v: Serializer)

nitcorn $ HttpResponse :: core_serialize_to

Actual serialization of self to serializer
redef fun finalize

nitcorn :: sessions $ HttpResponse :: finalize

Finalize this response before sending it over HTTP
redef init from_deserializer(v: Deserializer)

nitcorn $ HttpResponse :: from_deserializer

Create an instance of this class from the deserializer
redef init init(status_code: Int)

nitcorn $ HttpResponse :: init

All properties

fun !=(other: nullable Object): Bool

core :: Object :: !=

Have self and other different values?
fun ==(other: nullable Object): Bool

core :: Object :: ==

Have self and other the same value?
type CLASS: Class[SELF]

core :: Object :: CLASS

The type of the class of self.
type SELF: Object

core :: Object :: SELF

Type of this instance, automatically specialized in every class
protected fun accept_json_serializer(v: JsonSerializer)

serialization :: Serializable :: accept_json_serializer

Refinable service to customize the serialization of this class to JSON
protected fun accept_msgpack_attribute_counter(v: AttributeCounter)

serialization :: Serializable :: accept_msgpack_attribute_counter

Hook to customize the behavior of the AttributeCounter
protected fun accept_msgpack_serializer(v: MsgPackSerializer)

serialization :: Serializable :: accept_msgpack_serializer

Hook to customize the serialization of this class to MessagePack
protected fun add_to_bundle(bundle: NativeBundle, key: JavaString)

serialization :: Serializable :: add_to_bundle

Called by []= to dynamically choose the appropriate method according
fun body: Writable

nitcorn :: HttpResponse :: body

Body of this response
fun body=(body: Writable)

nitcorn :: HttpResponse :: body=

Body of this response
protected fun class_factory(name: String): CLASS

core :: Object :: class_factory

Implementation used by get_class to create the specific class.
fun class_name: String

core :: Object :: class_name

The class name of the object.
fun color_status: String

nitcorn :: HttpResponse :: color_status

Return self status colored for console.
fun core_serialize_to(serializer: Serializer)

serialization :: Serializable :: core_serialize_to

Actual serialization of self to serializer
fun csv(csv: nullable CsvDocument, status: nullable Int)

nitcorn :: HttpResponse :: csv

Write data as CSV and set the right content type header.
fun error(status: Int)

nitcorn :: HttpResponse :: error

TODO The error message should be parameterizable.
fun files: Array[String]

nitcorn :: HttpResponse :: files

Files appended after body
protected fun files=(files: Array[String])

nitcorn :: HttpResponse :: files=

Files appended after body
fun finalize

nitcorn :: HttpResponse :: finalize

Finalize this response before sending it over HTTP
init from_deserializer(deserializer: Deserializer)

serialization :: Serializable :: from_deserializer

Create an instance of this class from the deserializer
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun hash: Int

core :: Object :: hash

The hash code of the object.
fun header: HashMap[String, String]

nitcorn :: HttpResponse :: header

Headers of this response as a Map
protected fun header=(header: HashMap[String, String])

nitcorn :: HttpResponse :: header=

Headers of this response as a Map
fun html(html: nullable Writable, status: nullable Int)

nitcorn :: HttpResponse :: html

Write data as HTML and set the right content type header.
fun http_version: String

nitcorn :: HttpResponse :: http_version

HTTP protocol version
fun http_version=(http_version: String)

nitcorn :: HttpResponse :: http_version=

HTTP protocol version
init init

core :: Object :: init

fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
intern fun is_same_instance(other: nullable Object): Bool

core :: Object :: is_same_instance

Return true if self and other are the same instance (i.e. same identity).
fun is_same_serialized(other: nullable Object): Bool

core :: Object :: is_same_serialized

Is self the same as other in a serialization context?
intern fun is_same_type(other: Object): Bool

core :: Object :: is_same_type

Return true if self and other have the same dynamic type.
fun json(json: nullable Serializable, status: nullable Int, plain: nullable Bool, pretty: nullable Bool)

nitcorn :: HttpResponse :: json

Write data as JSON and set the right content type header.
fun json_error(message: String, status: Int)

nitcorn :: HttpResponse :: json_error

Write error as JSON.
protected fun msgpack_extra_array_items: Int

serialization :: Serializable :: msgpack_extra_array_items

Hook to request a larger than usual metadata array
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun output

core :: Object :: output

Display self on stdout (debug only).
intern fun output_class_name

core :: Object :: output_class_name

Display class name on stdout (debug only).
fun pug(pug_string: nullable String, json: nullable Serializable, status: nullable Int)

nitcorn :: HttpResponse :: pug

Render pug_string with the command cli pug and use data from json
fun pug_file(file: String, json: nullable Serializable, status: nullable Int)

nitcorn :: HttpResponse :: pug_file

Render file with the command cli pug and use data from json
fun redirect(location: String, status: nullable Int)

nitcorn :: HttpResponse :: redirect

Redirect response to location
fun render: Writable

nitcorn :: HttpResponse :: render

Get this reponse as a string according to HTTP protocol
fun send(raw_data: nullable Writable, status: nullable Int)

nitcorn :: HttpResponse :: send

Write data in body response and send it.
fun sent: Bool

nitcorn :: HttpResponse :: sent

Was this request sent by a handler?
protected fun sent=(sent: Bool)

nitcorn :: HttpResponse :: sent=

Was this request sent by a handler?
fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
fun serialize_msgpack(plain: nullable Bool): Bytes

serialization :: Serializable :: serialize_msgpack

Serialize self to MessagePack bytes
fun serialize_to(serializer: Serializer)

serialization :: Serializable :: serialize_to

Serialize self to serializer
fun serialize_to_json(plain: nullable Bool, pretty: nullable Bool): String

serialization :: Serializable :: serialize_to_json

Serialize self to JSON
fun session: nullable Session

nitcorn :: HttpResponse :: session

A Session to associate with a response
fun session=(session: nullable Session)

nitcorn :: HttpResponse :: session=

A Session to associate with a response
fun status_code: Int

nitcorn :: HttpResponse :: status_code

Status code of this response (200, 404, etc.)
fun status_code=(status_code: Int)

nitcorn :: HttpResponse :: status_code=

Status code of this response (200, 404, etc.)
fun status_message: nullable String

nitcorn :: HttpResponse :: status_message

Return the message associated to status_code
intern fun sys: Sys

core :: Object :: sys

Return the global sys object, the only instance of the Sys class.
fun template(tpl: nullable TemplateString, values: nullable Map[String, nullable Writable], status: nullable Int)

nitcorn :: HttpResponse :: template

Render the TemplateString tpl with values and write it as html.
fun template_file(file: String, values: nullable Map[String, nullable Writable], status: nullable Int)

nitcorn :: HttpResponse :: template_file

Render file as a TemplateString with values and write it as html.
fun template_string(tpl_string: nullable String, values: nullable Map[String, nullable Writable], status: nullable Int)

nitcorn :: HttpResponse :: template_string

Render file as a TemplateString with values and write it as html.
fun to_json: String

serialization :: Serializable :: to_json

Serialize self to plain JSON
abstract fun to_jvalue(env: JniEnv): JValue

core :: Object :: to_jvalue

fun to_pretty_json: String

serialization :: Serializable :: to_pretty_json

Serialize self to plain pretty JSON
fun to_s: String

core :: Object :: to_s

User readable representation of self.
package_diagram nitcorn::HttpResponse HttpResponse serialization::Serializable Serializable nitcorn::HttpResponse->serialization::Serializable core::Object Object serialization::Serializable->core::Object ...core::Object ... ...core::Object->core::Object

Ancestors

interface Object

core :: Object

The root of the class hierarchy.

Parents

interface Serializable

serialization :: Serializable

Instances of this class can be passed to Serializer::serialize

Class definitions

nitcorn $ HttpResponse
# A response to send over HTTP
class HttpResponse
	serialize

	# HTTP protocol version
	var http_version = "HTTP/1.0" is writable

	# Status code of this response (200, 404, etc.)
	var status_code: Int is writable

	# Return the message associated to `status_code`
	fun status_message: nullable String do return http_status_codes[status_code]

	# Headers of this response as a `Map`
	var header = new HashMap[String, String]

	# Body of this response
	var body: Writable = "" is writable

	# Files appended after `body`
	var files = new Array[String]

	# Finalize this response before sending it over HTTP
	fun finalize
	do
		# Set the content length if not already set
		if not header.keys.has("Content-Length") then
			# Size of the body
			var len
			var body = self.body
			if body isa Text then
				len = body.byte_length
			else if body isa Bytes then
				len = body.length
			else
				# We need the length, but there is no length in a writable.
				# So just render it as a bytes then measure :/
				body = body.write_to_bytes
				len = body.length
				# Keep the body as bytes since we have it
				self.body = body
			end

			# Size of included files
			for path in files do
				# TODO handle these error cases elsewhere, an error here will result in an invalid response
				if not path.file_exists then
					print_error "File does not exists at '{path}'"
					continue
				end

				var stat = path.file_stat
				if stat == null then
					print_error "Failed to stat file at '{path}'"
					continue
				end

				len += stat.size
			end

			# Set header
			header["Content-Length"] = len.to_s
		end

		# Set server ID
		if not header.keys.has("Server") then header["Server"] = "nitcorn"
	end

	# Get this reponse as a string according to HTTP protocol
	fun render: Writable
	do
		finalize

		var buf = new Template
		buf.add("{http_version} {status_code} {status_message or else ""}\r\n")
		for key, value in header do
			buf.add("{key}: {value}\r\n")
		end
		buf.add("\r\n")
		buf.add body
		return buf
	end
end
lib/nitcorn/http_response.nit:25,1--107,3

nitcorn :: sessions $ HttpResponse
redef class HttpResponse
	# A `Session` to associate with a response
	var session: nullable Session = null is writable

	redef fun finalize
	do
		super

		var session = self.session
		if session != null then
			header["Set-Cookie"] = "nitcorn_session={session.id_hash}; HttpOnly"
		else
			# Make sure there are no cookie left client side
			header["Set-Cookie"] = "nitcorn_session=; HttpOnly; expires=Thu, 01 Jan 1970 00:00:00 GMT"
		end
	end
end
lib/nitcorn/sessions.nit:55,1--71,3

popcorn :: pop_handlers $ HttpResponse
redef class HttpResponse

	# Was this request sent by a handler?
	var sent = false

	private fun check_sent do
		if sent then print "Warning: Headers already sent!"
	end

	# Write data in body response and send it.
	fun send(raw_data: nullable Writable, status: nullable Int) do
		if raw_data != null then
			body = raw_data
		end
		if status != null then
			status_code = status
		else
			status_code = 200
		end
		check_sent
		sent = true
	end

	# Write data as HTML and set the right content type header.
	fun html(html: nullable Writable, status: nullable Int) do
		header["Content-Type"] = media_types["html"].as(not null)
		send(html, status)
	end

	# Write data as CSV and set the right content type header.
	fun csv(csv: nullable CsvDocument, status: nullable Int) do
		header["Content-Type"] = media_types["csv"].as(not null)
		if csv == null then
			send(null, status)
		else
			send(csv.write_to_string, status)
		end
	end

	# Redirect response to `location`
	#
	# Use by default 303 See Other as it is the RFC
	# way to redirect web applications to a new URI.
	fun redirect(location: String, status: nullable Int) do
		header["Location"] = location
		if status != null then
			status_code = status
		else
			status_code = 303
		end
		check_sent
		sent = true
	end

	# TODO The error message should be parameterizable.
	fun error(status: Int) do
		html("Error", status)
	end
end
lib/popcorn/pop_handlers.nit:422,1--480,3

popcorn :: pop_logging $ HttpResponse
redef class HttpResponse
	# Return `self` status colored for console.
	fun color_status: String do
		if status_code >= 100 and status_code < 200 then return status_code.to_s.gray
		if status_code >= 200 and status_code < 300 then return status_code.to_s.green
		if status_code >= 300 and status_code < 400 then return status_code.to_s.blue
		if status_code >= 400 and status_code < 500 then return status_code.to_s.yellow
		if status_code >= 500 and status_code < 600 then return status_code.to_s.red
		return status_code.to_s
	end
end
lib/popcorn/pop_logging.nit:103,1--113,3

popcorn :: pop_json $ HttpResponse
redef class HttpResponse

	# Write data as JSON and set the right content type header.
	fun json(json: nullable Serializable, status: nullable Int, plain, pretty: nullable Bool) do
		header["Content-Type"] = media_types["json"].as(not null)
		if json == null then
			send(null, status)
		else
			send(json.serialize_to_json(plain or else true, pretty or else false), status)
		end
	end

	# Write error as JSON.
	#
	# Format: `{"message": message, "status": status}`
	fun json_error(message: String, status: Int) do
		var obj = new JsonObject
		obj["status"] = status
		obj["message"] = message
		json(obj, status)
	end
end
lib/popcorn/pop_json.nit:167,1--188,3

popcorn :: pop_templates $ HttpResponse
redef class HttpResponse

	# Render the TemplateString `tpl` with `values` and write it as html.
	fun template(tpl: nullable TemplateString, values: nullable Map[String, nullable Writable], status: nullable Int) do
		if tpl != null and values != null then
			for k, v in values do
				if not tpl.has_macro(k) or v == null then continue
				tpl.replace(k, v)
			end
		end
		html(tpl, status)
	end

	# Render `file` as a TemplateString with `values` and write it as html.
	fun template_string(tpl_string: nullable String, values: nullable Map[String, nullable Writable], status: nullable Int) do
		var tpl = new TemplateString(tpl_string or else "")
		template(tpl, values, status)
	end

	# Render `file` as a TemplateString with `values` and write it as html.
	fun template_file(file: String, values: nullable Map[String, nullable Writable], status: nullable Int) do
		var tpl = new TemplateString.from_file(file)
		template(tpl, values, status)
	end

	# Render `pug_string` with the command cli `pug` and use data from `json`
	#
	# See https://pugjs.org/api/getting-started.html for more details on pug.
	fun pug(pug_string: nullable String, json: nullable Serializable, status: nullable Int) do
		var process
		if json == null then
			process = new ProcessDuplex("pug", "-D")
		else
			process = new ProcessDuplex("pug", "-D", "-O", json.to_json)
		end
		var out = process.write_and_read(pug_string or else "")
		process.close
		html(out, status)
	end

	# Render `file` with the command cli `pug` and use data from `json`
	#
	# See https://pugjs.org/api/getting-started.html for more details on pug.
	fun pug_file(file: String, json: nullable Serializable, status: nullable Int) do
		pug(file.to_path.read_all, json, status)
	end
end
lib/popcorn/pop_templates.nit:89,1--135,3