module HTTP::FormData
Overview
Contains utilities for parsing multipart/form-data
messages, which are commonly used for encoding HTML form data.
Examples
Commonly, you'll want to parse a from response from a HTTP request, and process it. An example server which performs this task is shown below.
require "http" server = HTTP::Server.new do |context| name = nil file = nil HTTP::FormData.parse(context.request) do |part| case part.name when "name" name = part.body.gets_to_end when "file" file = File.tempfile("upload") do |file| IO.copy(part.body, file) end end end unless name && file context.response.respond_with_status(:bad_request) next end context.response << file.path end server.bind_tcp 8085 server.listen
To test the server, use the curl command below.
$ curl http://localhost:8085/ -F name=foo -F file=@/path/to/test.file /tmp/upload.Yxn7cc
Another common case is sending formdata to a server using HTTP::Client. Here is an example showing how to upload a file to the server above in crystal.
require "http" IO.pipe do |reader, writer| channel = Channel(String).new(1) spawn do HTTP::FormData.build(writer) do |formdata| channel.send(formdata.content_type) formdata.field("name", "foo") File.open("foo.png") do |file| metadata = HTTP::FormData::FileMetadata.new(filename: "foo.png") headers = HTTP::Headers{"Content-Type" => "image/png"} formdata.file("file", file, metadata, headers) end end writer.close end headers = HTTP::Headers{"Content-Type" => channel.receive} response = HTTP::Client.post("http://localhost:8085/", body: reader, headers: headers) puts "Response code #{response.status_code}" puts "File path: #{response.body}" end
Defined in:
http/formdata.crhttp/formdata/builder.cr
http/formdata/parser.cr
http/formdata/part.cr
Class Method Summary
- .build(response : HTTP::Server::Response, boundary = MIME::Multipart.generate_boundary, &)
Builds a multipart/form-data message, yielding a
FormData::Builder
object to the block which writes to response using *boundary. - .build(io, boundary = MIME::Multipart.generate_boundary, &)
Builds a multipart/form-data message, yielding a
FormData::Builder
object to the block which writes to io using boundary. - .parse(io, boundary, &)
Parses a multipart/form-data message, yielding a
FormData::Part
. - .parse(request : HTTP::Request, &)
Parses a multipart/form-data message, yielding a
FormData::Part
. - .parse_content_disposition(content_disposition) : Tuple(String, FileMetadata)
Parses a
Content-Disposition
header string into a field name andFileMetadata
.
Class Method Detail
def self.build(response : HTTP::Server::Response, boundary = MIME::Multipart.generate_boundary, &)Source
Builds a multipart/form-data message, yielding a FormData::Builder
object to the block which writes to response using *boundary. Content-Type is set on response and Builder#finish
is called on the builder when the block returns.
require "http" io = IO::Memory.new response = HTTP::Server::Response.new io HTTP::FormData.build(response, "boundary") do |builder| builder.field("foo", "bar") end response.close response.headers["Content-Type"] # => "multipart/form-data; boundary=\"boundary\"" io.to_s # => "HTTP/1.1 200 OK\r\nContent-Type: multipart/form-data; boundary=\"boundary\"\r\nContent-Length: 75\r\n\r\n--boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n--boundary--"
See: FormData::Builder
def self.build(io, boundary = MIME::Multipart.generate_boundary, &)Source
Builds a multipart/form-data message, yielding a FormData::Builder
object to the block which writes to io using boundary. Builder#finish
is called on the builder when the block returns.
require "http" io = IO::Memory.new HTTP::FormData.build(io, "boundary") do |builder| builder.field("foo", "bar") end io.to_s # => "--boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\n\r\nbar\r\n--boundary--"
See: FormData::Builder
def self.parse(io, boundary, &)Source
Parses a multipart/form-data message, yielding a FormData::Part
.
require "http" form_data = "--aA40\r\nContent-Disposition: form-data; name=\"field1\"\r\n\r\nfield data\r\n--aA40--" HTTP::FormData.parse(IO::Memory.new(form_data), "aA40") do |part| part.name # => "field1" part.body.gets_to_end # => "field data" end
See: FormData::Parser
def self.parse(request : HTTP::Request, &)Source
Parses a multipart/form-data message, yielding a FormData::Part
.
require "http" headers = HTTP::Headers{"Content-Type" => "multipart/form-data; boundary=aA40"} body = "--aA40\r\nContent-Disposition: form-data; name=\"field1\"\r\n\r\nfield data\r\n--aA40--" request = HTTP::Request.new("POST", "/", headers, body) HTTP::FormData.parse(request) do |part| part.name # => "field1" part.body.gets_to_end # => "field data" end
See: FormData::Parser
def self.parse_content_disposition(content_disposition) : Tuple(String, FileMetadata)Source
Parses a Content-Disposition
header string into a field name and FileMetadata
. Please note that the Content-Disposition
header for multipart/form-data
is not compatible with the original definition in RFC 2183, but are instead specified in RFC 2388.
© 2012–2021 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/1.2.1/HTTP/FormData.html