Add site contents, including the guide. Add license information.

This commit is contained in:
Sergio Benitez 2017-04-16 19:48:59 -07:00
parent 9b7f58448a
commit b5ef6ec85b
19 changed files with 3316 additions and 0 deletions

View File

@ -213,3 +213,5 @@ Rocket is licensed under either of the following, at your option:
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
The Rocket website source is licensed under [separate terms](site/README.md#license).

View File

@ -11,4 +11,5 @@ if [ -z ${1} ] || [ -z ${2} ]; then
fi
find . -name "*.toml" | xargs sed -i.bak "s/${1}/${2}/g"
find site/ -name "*.md" | xargs sed -i.bak "s/${1}/${2}/g"
find . -name "*.bak" | xargs rm

674
site/LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

29
site/README.md Normal file
View File

@ -0,0 +1,29 @@
# Rocket Website Source
This directory contains the source files for the content on [Rocket's
website](https://rocket.rs).
## Contents
This directory contains the following:
* `index.toml` - Source data for the index (`/`).
* `news.toml` - Source data for the news page (`/news`).
* `overview.toml` - Source data for the overview page (`/overview`).
* `guide.md` - Index page for the guide (`/guide`).
* `news/*.md` - News articles linked to from `news.toml`.
* `guide/*.md` - Guide pages linked to from `guide.md`.
## Guide
The source files for the [Rocket Programming Guide](https://rocket.rs/guide/)
can be found in the `guide/` directory. One exception is the root of the guide,
which is `guide.md`.
Cross-linking to pages in the guide is accomplished via absolute links rooted at
`/guide/`. To link to the page whose source is at `guide/page.md` in this
directory, for instance, link to `/guide/page`.
# License
The Rocket website source is licensed under the [GNU General Public License v3.0](LICENSE).

43
site/guide.md Normal file
View File

@ -0,0 +1,43 @@
# The Rocket Programming Guide
Welcome to Rocket!
This is the official guide. It is designed to serve as a starting point to
writing web application with Rocket and Rust. The guide is also designed to be a
reference for experienced Rocket developers. This guide is conversational in
tone. For concise and purely technical documentation, see the [API
documentation](https://api.rocket.rs).
The guide is split into several sections, each with a focus on a different
aspect of Rocket. The sections are:
- **[Introduction](introduction/):** introduces Rocket and its philosophy.
- **[Quickstart](quickstart/):** presents the minimal steps necessary to
run your first Rocket application.
- **[Getting Started](getting-started/):** a gentle introduction to getting
your first Rocket application running.
- **[Overview](overview/):** describes the core concepts of Rocket.
- **[Requests](requests/):** discusses handling requests: control-flow,
parsing, and validating.
- **[Responses](responses/):** discusses generating responses.
- **[State](state/):** how to manage state in a Rocket application.
- **[Testing](testing/):** how to unit and integration test a Rocket
application.
- **[Pastebin](pastebin/):** a tutorial on how to create a pastebin with
Rocket.
- **[Conclusion](conclusion/):** concludes the guide and discusses next steps
for learning.
## Getting Help
The official community support channels are the `#rocket` IRC channel on the
[Mozilla IRC Server](https://wiki.mozilla.org/IRC) at `irc.mozilla.org` and the
bridged [Rocket room on
Matrix](https://riot.im/app/#/room/#mozilla_#rocket:matrix.org). If you're not
familiar with IRC, we recommend chatting through [Matrix via
Riot](https://riot.im/app/#/room/#mozilla_#rocket:matrix.org) or via the [Kiwi
web IRC client](https://kiwiirc.com/client/irc.mozilla.org/#rocket). You can
learn more about IRC via Mozilla's [Getting Started with
IRC](https://developer.mozilla.org/en-US/docs/Mozilla/QA/Getting_Started_with_IRC)
guide.

28
site/guide/conclusion.md Normal file
View File

@ -0,0 +1,28 @@
# Conclusion
We hope you agree that Rocket is a refreshing take on web frameworks. As with
any software project, Rocket is _alive_. There are always things to improve, and
we're happy to take the best ideas. If you have something in mind, please
[submit an issue](https://github.com/SergioBenitez/Rocket/issues).
## Getting Help
If you find yourself having trouble developing Rocket applications, you can get
help via the `#rocket` IRC channel on the [Mozilla IRC
Server](https://wiki.mozilla.org/IRC) at `irc.mozilla.org` and the bridged
[Rocket room on Matrix](https://riot.im/app/#/room/#mozilla_#rocket:matrix.org).
If you're not familiar with IRC, we recommend chatting through [Matrix via
Riot](https://riot.im/app/#/room/#mozilla_#rocket:matrix.org) or via the [Kiwi
web IRC client](https://kiwiirc.com/client/irc.mozilla.org/#rocket). You can
learn more about IRC via Mozilla's [Getting Started with
IRC](https://developer.mozilla.org/en-US/docs/Mozilla/QA/Getting_Started_with_IRC)
guide.
## What's next?
The best way to learn Rocket is to _build something_. It should be fun and easy,
and there's always someone to help. Alternatively, you can read through the
[Rocket examples](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples)
or the [Rocket source
code](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/lib/src). Whatever you
decide to do next, we hope you have a blast!

View File

@ -0,0 +1,95 @@
# Getting Started
Let's create and run our first Rocket application. We'll ensure we have a
compatible version of Rust, create a new Cargo project that depends on Rocket,
and then run the application.
## Installing Rust
Rocket makes abundant use of Rust's syntax extensions. Because syntax extensions
don't yet have a stable compiler API, we'll need to use a nightly version of
Rust. If you already have a working installation of the latest Rust nightly,
feel free to skip to the next section.
To install a nightly version of Rust, we recommend using `rustup`. Install
`rustup` by following the instructions on [its website](https://rustup.rs/).
Once `rustup` is installed, configure Rust nightly as your default toolchain by
running the command:
```sh
rustup default nightly
```
If you prefer, once we setup a project directory in the following section, you
can use per-directory overrides to use the nightly version _only_ for your
Rocket project by running the following command in the directory:
```sh
rustup override set nightly
```
## Nightly Version
Rocket requires the _latest_ version of Rust nightly to function. If your Rocket
application suddently stops building, ensure you're using the latest version of
Rust nightly and Rocket by updating your toolchain and dependencies with:
```sh
rustup update && cargo update
```
## Hello, world!
Let's write our first Rocket application! Start by creating a new binary-based
Cargo project and changing into the new directory:
```sh
cargo new hello-rocket --bin
cd hello-rocket
```
Now, add Rocket and its code generation facilities as dependencies of your
project by ensuring your `Cargo.toml` contains the following:
```
[dependencies]
rocket = "0.2.5"
rocket_codegen = "0.2.5"
```
Modify `src/main.rs` so that it contains the code for the Rocket `Hello, world!`
program, which we reproduce below:
```rust
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}
```
We won't explain exactly what the program does now; we leave that for the rest
of the guide. In short, it creates an `index` route, _mounts_ the route at the
`/` path, and launches the application. Run the program with `cargo run`. You
should see the following:
```sh
🔧 Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: {logical cores}
🛰 Mounting '/':
=> GET /
🚀 Rocket has launched from http://localhost:8000...
```
Visit `http://localhost:8000` to see your first Rocket application in action!

View File

@ -0,0 +1,43 @@
# Introduction
Rocket is a web framework for Rust. If you'd like, you can think of Rocket as
being a more flexible, friendly medley of [Rails](http://rubyonrails.org),
[Flask](http://flask.pocoo.org/),
[Bottle](http://bottlepy.org/docs/dev/index.html), and
[Yesod](http://www.yesodweb.com/). We prefer to think of Rocket as something
new. Rocket aims to be fast, easy, and flexible. It also aims to be _fun_, and
it accomplishes this by ensuring that you write as little code as needed to
accomplish your task. This guide introduces you to the core, intermediate, and
advanced concepts of Rocket. After reading this guide, you should find yourself
being _very_ productive with Rocket.
## Audience
Readers are assumed to have a good grasp of the Rust programming language.
Readers new to Rust are encouraged to read the [Rust
Book](https://doc.rust-lang.org/book/). This guide also assumes a basic
understanding of web application fundamentals, such as routing and HTTP.
## Foreword
Rocket's design is centered around three core philosophies:
* **Function declaration and parameter types should contain all the necessary
information to validate and process a request.** This immediately prohibits
APIs where request state is retrieved from a global context. As a result,
request handling is **self-contained** in Rocket: handlers are regular
functions with regular arguments.
* **All request handling information should be typed.** Because the web and
HTTP are themselves untyped (or _stringly_ typed, as some call it), this
means that something or someone has to convert strings to native types.
Rocket does this for you with zero programming overhead.
* **Decisions should not be forced.** Templates, serialization, sessions, and
just about everything else are all pluggable, optional components. While
Rocket has official support and libraries for each of these, they are
completely optional and swappable.
These three ideas dictate Rocket's interface, and you will find the ideas
embedded in Rocket's core features.

317
site/guide/overview.md Normal file
View File

@ -0,0 +1,317 @@
# Overview
Rocket provides primitives to build web servers and applications with Rust: the
rest is up to you. In short, Rocket provides routing, pre-processing of
requests, and post-processing of responses. Your application code instructs
Rocket on what to pre-process and post-process and fills the gaps between
pre-processing and post-processing.
## Lifecycle
Rocket's main task is to listen for incoming web requests, dispatch the request
to the application code, and return a response to the client. We call the
process that goes from request to response: the _lifecycle_. We summarize the
lifecycle as the sequence of steps:
1. **Routing**
Rocket parses an incoming HTTP request into native structures that your code
operates on indirectly. Rocket determines which request handler to invoke by
matching against route attributes declared by your application.
2. **Validation**
Rocket validates the incoming request against types and request guards
present in the matched route. If validation fails, Rocket _forwards_ the
request to the next matching route or calls an _error handler_.
3. **Processing**
The request handler associated with the route is invoked with validated
arguments. This is the main business logic of the application. Processing
completes by returning a `Response`.
4. **Response**
The returned `Response` is processed. Rocket generates the appropriate HTTP
response and sends it to the client. This completes the lifecycle. Rocket
continues listening for requests, restarting the lifecycle for each incoming
request.
The remainder of this section details the _routing_ phase as well as additional
components needed for Rocket to begin dispatching requests to request handlers.
The sections following describe the request and response phases.
## Routing
Rocket applications are centered around routes and handlers.
A _handler_ is simply a function that takes an arbitrary number of arguments and
returns any arbitrary type. A _route_ is a combination of:
* A set of parameters to match an incoming request against.
* A handler to process the request and return a response.
The parameters to match against include static paths, dynamic paths, path
segments, forms, query strings, request format specifiers, and body data. Rocket
uses attributes, which look like function decorators in other languages, to make
declaring routes easy. Routes are declared by annotating a function, the
handler, with the set of parameters to match against. A complete route
declaration looks like this:
```rust
#[get("/world")] // <- route attribute
fn world() -> &'static str { // <- request handler
"Hello, world!"
}
```
This declares the `world` route to match against the static path `"/world"` on
incoming `GET` requests. The `world` route is simple, but additional route
parameters are necessary when building more interesting applications. The
[Requests](/guide/requests) section describes the available options for
constructing routes.
## Mounting
Before Rocket can dispatch requests to a route, the route needs to be _mounted_.
Mounting a route is like namespacing it. Routes are mounted via the `mount`
method on a `Rocket` instance. Rocket instances can be created with the
`ignite()` static method.
The `mount` method takes **1)** a path to namespace a list of routes under, and
**2)** a list of route handlers through the `routes!` macro. The `routes!` macro
ties Rocket's code generation to your application.
For instance, to mount the `world` route we declared above, we would use the
following code:
```rust
rocket::ignite().mount("/hello", routes![world])
```
Altogether, this creates a new `Rocket` instance via the `ignite` function and
mounts the `world` route to the `"/hello"` path. As a result, `GET` requests to
the `"/hello/world"` path will be directed to the `world` function.
### Namespacing
When a route is declared inside a module other than the root, you may find
yourself with unexpected errors when mounting:
```rust
mod other {
#[get("/world")]
pub fn world() -> &'static str {
"Hello, world!"
}
}
use other::world;
fn main() {
// error[E0425]: cannot find value `static_rocket_route_info_for_world` in this scope
rocket::ignite().mount("/hello", routes![world])
}
```
This occurs because the `routes!` macro implicitly converts the route's name
into the name of a structure generated by Rocket's code generation. The solution
is to name the route by a module path instead:
```rust
rocket::ignite().mount("/hello", routes![other::world])
```
## Launching
Now that Rocket knows about the route, you can tell Rocket to start accepting
requests via the `launch` method. The method starts up the server and waits for
incoming requests. When a request arrives, Rocket finds the matching route and
dispatches the request to the route's handler.
We typically call `launch` from the `main` function. Our complete _Hello,
world!_ application thus looks like:
```rust
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/world")]
fn world() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().mount("/hello", routes![world]).launch();
}
```
Note that we've added the `#![feature(plugin)]` and `#![plugin(rocket_codegen)]`
lines to tell Rust that we'll be using Rocket's code generation plugin. We've
also imported the `rocket` crate into our namespace via `extern crate rocket`.
Finally, we call the `launch` method in the `main` function.
Running the application, the console shows:
```sh
🔧 Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: {logical cores}
🛰 Mounting '/world':
=> GET /hello/world
🚀 Rocket has launched from http://localhost:8000...
```
If we visit `localhost:8000/hello/world`, we see `Hello, world!`, exactly as
we expected.
A version of this example's complete crate, ready to `cargo run`, can be found
on
[GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/hello_world).
You can find dozens of other complete examples, spanning all of Rocket's
features, in the [GitHub examples
directory](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/).
## Configuration
At any point in time, a Rocket application is operating in a given
_configuration environment_. There are three such environments:
* `development` (short: `dev`)
* `staging` (short: `stage`)
* `production` (short: `prod`)
Without any action, Rocket applications run in the `development` environment.
The environment can be changed via the `ROCKET_ENV` environment variable. For
example, to launch the `Hello, world!` application in the `staging` environment,
we can run:
```sh
ROCKET_ENV=stage cargo run
```
You'll likely need `sudo` for the command to succeed since `staging` defaults to
listening on port `80`. Note that you can use the short or long form of the
environment name to specify the environment, `stage` _or_ `staging` here. Rocket
tells us the environment we have chosen and its configuration when it launches:
```sh
$ sudo ROCKET_ENV=staging cargo run
🔧 Configured for staging.
=> address: 0.0.0.0
=> port: 80
=> log: normal
=> workers: {logical cores}
🛰 Mounting '/':
=> GET /
🚀 Rocket has launched from http://0.0.0.0:80...
```
Configuration settings can be changed in one of two ways: via the `Rocket.toml`
configuration file, or via environment variables.
### Configuration File
A `Rocket.toml` file can be used to specify the configuration parameters for
each environment. The file is optional. If it is not present, the default
configuration parameters are used.
The file must be a series of TOML tables, at most one for each environment and
an optional "global" table, where each table contains key-value pairs
corresponding to configuration parameters for that environment. If a
configuration parameter is missing, the default value is used. The following is
a complete `Rocket.toml` file, where every standard configuration parameter is
specified with the default value:
```toml
[development]
address = "localhost"
port = 8000
workers = max(number_of_cpus, 2)
log = "normal"
[staging]
address = "0.0.0.0"
port = 80
workers = max(number_of_cpus, 2)
log = "normal"
[production]
address = "0.0.0.0"
port = 80
workers = max(number_of_cpus, 2)
log = "critical"
```
The `workers` parameter is computed by Rocket automatically; the value above is
not valid TOML syntax.
The "global" pseudo-environment can be used to set and/or override configuration
parameters globally. A parameter defined in a `[global]` table sets, or
overrides if already present, that parameter in every environment. For example,
given the following `Rocket.toml` file, the value of `address` will be
`"1.2.3.4"` in every environment:
```toml
[global]
address = "1.2.3.4"
[development]
address = "localhost"
[production]
address = "0.0.0.0"
```
### Extras
In addition to overriding default configuration parameters, a configuration file
can also define values for any number of _extra_ configuration parameters. While
these parameters aren't used by Rocket directly, other libraries, or your own
application, can use them as they wish. As an example, the
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html) type
accepts a value for the `template_dir` configuration parameter. The parameter
can be set in `Rocket.toml` as follows:
```toml
[development]
template_dir = "dev_templates/"
[production]
template_dir = "prod_templates/"
```
This sets the `template_dir` extra configuration parameter to `"dev_templates/"`
when operating in the `development` environment and `"prod_templates/"` when
operating in the `production` environment. Rocket will prepend the `[extra]` tag
to extra configuration parameters when launching:
```sh
🔧 Configured for development.
=> ...
=> [extra] template_dir: "dev_templates/"
```
### Environment Variables
All configuration parameters, including extras, can be overridden through
environment variables. To override the configuration parameter `{param}`, use an
environment variable named `ROCKET_{PARAM}`. For instance, to override the
"port" configuration parameter, you can run your application with:
```sh
ROCKET_PORT=3721 cargo run
🔧 Configured for staging.
=> ...
=> port: 3721
```
Environment variables take precedence over all other configuration methods: if a
variable is set, it will be used as that parameter's value.

405
site/guide/pastebin.md Normal file
View File

@ -0,0 +1,405 @@
# Pastebin
To give you a taste of what a real Rocket application looks like, this section
of the guide is a tutorial on how to create a Pastebin application in Rocket. A
pastebin is a simple web application that allows users to upload a text document
and later retrieve it via a special URL. They're often used to share code
snippets, configuration files, and error logs. In this tutorial, we'll build a
simple pastebin service that allows users to upload a file from their terminal.
The service will respond back with a URL to the uploaded file.
## Finished Product
A souped-up, completed version of the application you're about to build is
deployed live at [paste.rs](https://paste.rs). Feel free to play with the
application to get a feel for how it works. For example, to upload a text
document named `test.txt`, you can do:
```sh
curl --data-binary @test.txt https://paste.rs/
# => https://paste.rs/IYu
```
The finished product is composed of the following routes:
* index: **GET /** - returns a simple HTML page with instructions about how
to use the service
* upload: **POST /** - accepts raw data in the body of the request and
responds with a URL of a page containing the body's content
* retrieve: **GET /&lt;id>** - retrieves the content for the paste with id
`<id>`
## Getting Started
Let's get started! First, create a fresh Cargo binary project named
`rocket-pastebin`:
```rust
cargo new --bin rocket-pastebin
cd rocket-pastebin
```
Then add the usual Rocket dependencies to the `Cargo.toml` file:
```toml
[dependencies]
rocket = "0.2.5"
rocket_codegen = "0.2.5"
```
And finally, create a skeleton Rocket application to work off of in
`src/main.rs`:
```rust
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
fn main() {
rocket::ignite().launch()
}
```
Ensure everything works by running the application:
```sh
cargo run
```
At this point, we haven't declared any routes or handlers, so visiting any page
will result in Rocket returning a **404** error. Throughout the rest of the
tutorial, we'll create the three routes and accompanying handlers.
## Index
The first route we'll create is the `index` route. This is the page users will
see when they first visit the service. As such, the route should field requests
of the form `GET /`. We declare the route and its handler by adding the `index`
function below to `src/main.rs`:
```rust
#[get("/")]
fn index() -> &'static str {
"
USAGE
POST /
accepts raw data in the body of the request and responds with a URL of
a page containing the body's content
GET /<id>
retrieves the content for the paste with id `<id>`
"
}
```
This declares the `index` route for requests to `GET /` as returning a static
string with the specified contents. Rocket will take the string and return it as
the body of a fully formed HTTP response with `Content-Type: text/plain`. You
can read more about how Rocket formulates responses at the [API documentation
for the Responder
trait](https://api.rocket.rs/rocket/response/trait.Responder.html).
Remember that routes first need to be mounted before Rocket dispatches requests
to them. To mount the `index` route, modify the main function so that it reads:
```rust
fn main() {
rocket::ignite().mount("/", routes![index]).launch()
}
```
You should now be able to `cargo run` the application and visit the root path
(`/`) to see the text being displayed.
## Uploading
The most complicated aspect of the pastebin, as you might imagine, is handling
upload requests. When a user attempts to upload a pastebin, our service needs to
generate a unique ID for the upload, read the data, write it out to a file or
database, and then return a URL with the ID. We'll take each of these one step
at a time, beginning with generating IDs.
### Unique IDs
Generating a unique and useful ID is an interesting topic, but it is outside the
scope of this tutorial. Instead, we simply provide the code for a `PasteID`
structure that represents a _probably_ unique ID. Read through the code, then
copy/paste it into a new file named `paste_id.rs` in the `src/` directory:
```rust
use std::fmt;
use std::borrow::Cow;
use rand::{self, Rng};
/// Table to retrieve base62 values from.
const BASE62: &'static [u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/// A _probably_ unique paste ID.
pub struct PasteID<'a>(Cow<'a, str>);
impl<'a> PasteID<'a> {
/// Generate a _probably_ unique ID with `size` characters. For readability,
/// the characters used are from the sets [0-9], [A-Z], [a-z]. The
/// probability of a collision depends on the value of `size`. In
/// particular, the probability of a collision is 1/62^(size).
pub fn new(size: usize) -> PasteID<'static> {
let mut id = String::with_capacity(size);
let mut rng = rand::thread_rng();
for _ in 0..size {
id.push(BASE62[rng.gen::<usize>() % 62] as char);
}
PasteID(Cow::Owned(id))
}
}
impl<'a> fmt::Display for PasteID<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
```
Then, in `src/main.rs`, add the following after `extern crate rocket`:
```rust
extern crate rand;
mod paste_id;
use paste_id::PasteID;
```
Finally, add a dependency for the `rand` crate to the `Cargo.toml` file:
```toml
[dependencies]
# existing Rocket dependencies...
rand = "0.3"
```
Then, ensure that your application builds with the new code:
```sh
cargo build
```
You'll likely see many "unused" warnings for the new code we've added: that's
okay and expected. We'll be using the new code soon.
### Processing
Believe it or not, the hard part is done! (_whew!_).
To process the upload, we'll need a place to store the uploaded files. To
simplify things, we'll store the uploads in a directory named `uploads/`. Create
an `upload` directory next to the `src` directory:
```sh
mkdir upload
```
For the `upload` route, we'll need to `use` a few items:
```rust
use std::io;
use std::path::Path;
use rocket::Data;
```
The [Data](https://api.rocket.rs/rocket/data/struct.Data.html) structure is key
here: it represents an unopened stream to the incoming request body data. We'll
use it to efficiently stream the incoming request to a file.
### Upload Route
We're finally ready to write the `upload` route. Before we show you the code,
you should attempt to write the route yourself. Here's a hint: a possible route
and handler signature look like this:
```rust
#[post("/", data = "<paste>")]
fn upload(paste: Data) -> io::Result<String>
```
Your code should:
1. Create a new `PasteID` of a length of your choosing.
2. Construct a filename inside `upload/` given the `PasteID`.
3. Stream the `Data` to the file with the constructed filename.
4. Construct a URL given the `PasteID`.
5. Return the URL to the client.
Here's our version (in `src/main.rs`):
```rust
#[post("/", data = "<paste>")]
fn upload(paste: Data) -> io::Result<String> {
let id = PasteID::new(3);
let filename = format!("upload/{id}", id = id);
let url = format!("{host}/{id}\n", host = "http://localhost:8000", id = id);
// Write the paste out to the file and return the URL.
paste.stream_to_file(Path::new(&filename))?;
Ok(url)
}
```
Make sure that the route is mounted at the root path:
```rust
fn main() {
rocket::ignite().mount("/", routes![index, upload]).launch()
}
```
Test that your route works via `cargo run`. From a separate terminal, upload a
file using `curl`. Then verify that the file was saved to the `upload` directory
with the correct ID:
```sh
# in the project root
cargo run
# in a seperate terminal
echo "Hello, world." | curl --data-binary @- http://localhost:8000
# => http://localhost:8000/eGs
# back to the terminal running the pastebin
<ctrl-c> # kill running process
ls upload # ensure the upload is there
cat upload/* # ensure that contents are correct
```
Note that since we haven't created a `GET /<id>` route, visting the returned URL
will result in a **404**. We'll fix that now.
## Retrieving Pastes
The final step is to create the `retrieve` route which, given an `<id>`, will
return the corresponding paste if it exists.
Here's a first take at implementing the `retrieve` route. The route below takes
in an `<id>` as a dynamic path element. The handler uses the `id` to construct a
path to the paste inside `upload/`, and then attempts to open the file at that
path, optionally returning the `File` if it exists. Rocket treats a `None`
[Responder](https://api.rocket.rs/rocket/response/trait.Responder.html#provided-implementations)
as a **404** error, which is exactly what we want to return when the requested
paste doesn't exist.
```rust
use std::fs::File;
#[get("/<id>")]
fn retrieve(id: &str) -> Option<File> {
let filename = format!("upload/{id}", id = id);
File::open(&filename).ok()
}
```
Unfortunately, there's a problem with this code. Can you spot the issue?
The issue is that the _user_ controls the value of `id`, and as a result, can
coerce the service into opening files inside `upload/` that aren't meant to be
opened. For instance, imagine that you later decide that a special file
`upload/_credentials.txt` will store some important, private information. If the
user issues a `GET` request to `/_credentials.txt`, the server will read and
return the `upload/_credentials.txt` file, leaking the sensitive information.
This is a big problem; it's known as the [full path disclosure
attack](https://www.owasp.org/index.php/Full_Path_Disclosure), and Rocket
provides the tools to prevent this and other kinds of attacks from happening.
To prevent the attack, we need to _validate_ `id` before we use it. Since the
`id` is a dynamic parameter, we can use Rocket's
[FromParam](https://api.rocket.rs/rocket/request/trait.FromParam.html) trait to
implement the validation and ensure that the `id` is a valid `PasteID` before
using it. We do this by implementing `FromParam` for `PasteID` in
`src/paste_id.rs`, as below:
```rust
use rocket::request::FromParam;
/// Returns `true` if `id` is a valid paste ID and `false` otherwise.
fn valid_id(id: &str) -> bool {
id.chars().all(|c| {
(c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9')
})
}
/// Returns an instance of `PasteID` if the path segment is a valid ID.
/// Otherwise returns the invalid ID as the `Err` value.
impl<'a> FromParam<'a> for PasteID<'a> {
type Error = &'a str;
fn from_param(param: &'a str) -> Result<PasteID<'a>, &'a str> {
match valid_id(param) {
true => Ok(PasteID(Cow::Borrowed(param))),
false => Err(param)
}
}
}
```
Then, we simply need to change the type of `id` in the handler to `PasteID`.
Rocket will then ensure that `<id>` represents a valid `PasteID` before calling
the `retrieve` route, preventing attacks on the `retrieve` route:
```rust
#[get("/<id>")]
fn retrieve(id: PasteID) -> Option<File> {
let filename = format!("upload/{id}", id = id);
File::open(&filename).ok()
}
```
Note that our `valid_id` function is simple and could be improved by, for
example, checking that the length of the `id` is within some known bound or
potentially blacklisting sensitive files as needed.
The wonderful thing about using `FromParam` and other Rocket traits is that they
centralize policies. For instance, here, we've centralized the policy for valid
`PasteID`s in dynamic parameters. At any point in the future, if other routes
are added that require a `PasteID`, no further work has to be done: simply use
the type in the signature and Rocket takes care of the rest.
## Conclusion
That's it! Ensure that all of your routes are mounted and test your application.
You've now written a simple (~75 line!) pastebin in Rocket! There are many
potential improvements to this small application, and we encourage you to work
through some of them to get a better feel for Rocket. Here are some ideas:
* Add a web form to the `index` where users can manually input new pastes.
Accept the form at `POST /`. Use `format` and/or `rank` to specify which of
the two `POST /` routes should be called.
* Support **deletion** of pastes by adding a new `DELETE /<id>` route. Use
`PasteID` to validate `<id>`.
* **Limit the upload** to a maximum size. If the upload exceeds that size,
return a **206** partial status code. Otherwise, return a **201** created
status code.
* Set the `Content-Type` of the return value in `upload` and `retrieve` to
`text/plain`.
* **Return a unique "key"** after each upload and require that the key is
present and matches when doing deletion. Use one of Rocket's core traits to
do the key validation.
* Add a `PUT /<id>` route that allows a user with the key for `<id>` to
replace the existing paste, if any.
* Add a new route, `GET /<id>/<lang>` that syntax highlights the paste with ID
`<id>` for language `<lang>`. If `<lang>` is not a known language, do no
highlighting. Possibly validate `<lang>` with `FromParam`.
* Use the [testing module](https://api.rocket.rs/rocket/testing/) to write
unit tests for your pastebin.
* Dispatch a thread before `launch`ing Rocket in `main` that periodically
cleans up idling old pastes in `upload/`.
You can find the full source code for the completed pastebin tutorial in the
[Rocket Github
Repo](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/pastebin).

21
site/guide/quickstart.md Normal file
View File

@ -0,0 +1,21 @@
# Quickstart
Rocket requires a recent nightly version of Rust. We recommend you use
[rustup](https://rustup.rs/) to install or configure such a version. If you
don't have Rust installed, the [getting started](/guide/getting-started) section
guides you through installing Rust.
## Running Examples
The absolute fastest way to start experimenting with Rocket is to clone the
Rocket repository and run the included examples in the `examples/` directory.
For instance, the following set of commands runs the `hello_world` example:
```sh
git clone https://github.com/SergioBenitez/rocket
cd rocket/examples/hello_world
cargo run
```
There are numerous examples. They can all be run with `cargo run`.

378
site/guide/requests.md Normal file
View File

@ -0,0 +1,378 @@
# Requests
If all we could do was match against static paths like `"/world"`, Rocket
wouldn't be much fun. Of course, Rocket allows you to match against just about
any information in an incoming request. This section describes the available
options and their effect on the application.
## Methods
A Rocket route attribute can be any one of `get`, `put`, `post`, `delete`,
`head`, `patch`, or `options`, each corresponding to the HTTP method to match
against. For example, the following attribute will match against `POST` requests
to the root path:
```rust
#[post("/")]
```
The grammar for these routes is defined formally in the
[rocket_codegen](https://api.rocket.rs/rocket_codegen/) API docs.
Rocket handles `HEAD` requests automatically when there exists a `GET` route
that would otherwise match. It does this by stripping the body from the
response, if there is one. You can also specialize the handling of a `HEAD`
request by declaring a route for it; Rocket won't interfere with `HEAD` requests
your application handles.
Because browsers only send `GET` and `POST` requests, Rocket _reinterprets_
requests under certain conditions. If a `POST` request contains a body of
`Content-Type: application/x-www-form-urlencoded`, and the form's **first**
field has the name `_method` and a valid HTTP method as its value, that field's
value is used as the method for the incoming request. This allows Rocket
applications to submit non-`POST` forms. The [todo
example](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/todo/static/index.html.tera#L47)
makes use of this feature to submit `PUT` and `DELETE` requests from a web form.
## Format
When receiving data, you can specify the Content-Type the route matches against
via the `format` route parameter. The parameter is a string of the Content-Type
expected. For example, to match `application/json` data, a route can be declared
as:
```rust
#[post("/user", format = "application/json", data = "<user>")]
fn new_user(user: JSON<User>) -> T { ... }
```
Note the `format` parameter in the `post` attribute. The `data` parameter is
described later in the [data](#data) section.
## Dynamic Paths
You can declare path segments as dynamic by using angle brackets around variable
names in a route's path. For example, if we wanted to say _Hello!_ to anything,
not just the world, we could declare a route and handler like so:
```rust
#[get("/hello/<name>")]
fn hello(name: &str) -> String {
format!("Hello, {}!", name)
}
```
If we were to mount the path at the root (`.mount("/", routes![hello])`), then
any request to a path with two non-empty segments, where the first segment is
`hello`, will be dispatched to the `hello` route. For example, if we were to
visit `/hello/John`, the application would respond with `Hello, John!`.
You can have any number of dynamic path segments, and the type of the path
segment can be any type that implements the [FromParam
trait](https://api.rocket.rs/rocket/request/trait.FromParam.html), including
your own! Rocket implements `FromParam` for many of the standard library types,
as well as a few special Rocket types. Here's a somewhat complicated route to
illustrate varied usage:
```rust
#[get("/hello/<name>/<age>/<cool>")]
fn hello(name: &str, age: u8, cool: bool) -> String {
if cool {
format!("You're a cool {} year old, {}!", age, name)
} else {
format!("{}, we need to talk about your coolness.", name)
}
}
```
## Forwarding
In this example above, what if `cool` isn't a `bool`? Or, what if `age` isn't a
`u8`? In this case, the request is _forwarded_ to the next matching route, if
there is any. This continues until a route doesn't forward the request or there
are no remaining routes to try. When there are no remaining matching routes, a
customizable **404 error** is returned.
Routes are tried in increasing _rank_ order. By default, routes with static
paths have a rank of 0 and routes with dynamic paths have a rank of 1. A route's
rank can be manually set with the `rank` route parameter.
To illustrate, consider the following routes:
```rust
#[get("/user/<id>")]
fn user(id: usize) -> T { ... }
#[get("/user/<id>", rank = 2)]
fn user_int(id: isize) -> T { ... }
#[get("/user/<id>", rank = 3)]
fn user_str(id: &str) -> T { ... }
```
Notice the `rank` parameters in `user_int` and `user_str`. If we run this
application with the routes mounted at the root, requests to `/user/<id>` will
be routed as follows:
1. The `user` route matches first. If the string at the `<id>` position is an
unsigned integer, then the `user` handler is called. If it is not, then the
request is forwarded to the next matching route: `user_int`.
2. The `user_int` route matches next. If `<id>` is a signed integer,
`user_int` is called. Otherwise, the request is forwarded.
3. The `user_str` route matches last. Since `<id>` is a always string, the
route always matches. The `user_str` handler is called.
Forwards can be _caught_ by using a `Result` or `Option` type. For example, if
the type of `id` in the `user` function was `Result<usize, &str>`, then `user`
would never forward. An `Ok` variant would indicate that `<id>` was a valid
`usize`, while an `Err` would indicate that `<id>` was not a `usize`. The
`Err`'s value would contain the string that failed to parse as a `usize`.
By the way, if you were to omit the `rank` parameter in the `user_str` or
`user_int` routes, Rocket would emit a warning indicating that the routes
_collide_, or can match against similar incoming requests. The `rank` parameter
resolves this collision.
## Dynamic Segments
You can also match against multiple segments by using `<param..>` in the route
path. The type of such parameters, known as _segments_ parameters, can be any
that implements
[FromSegments](https://api.rocket.rs/rocket/request/trait.FromSegments.html).
Segments parameters must be the final component of the path: any text after a
segments parameter in a path will result in a compile-time error.
As an example, the following route matches against all paths that begin with
`/page/`:
```rust
#[get("/page/<path..>")]
fn get_page(path: PathBuf) -> T { ... }
```
The path after `/page/` will be available in the `path` parameter. The
`FromSegments` implementation for `PathBuf` ensures that `path` cannot lead to
[path traversal attacks](https://www.owasp.org/index.php/Path_Traversal). With
this, a safe and secure static file server can implemented in 4 lines:
```rust
#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("static/").join(file)).ok()
}
```
## Request Guards
Sometimes we need data associated with a request that isn't a direct input.
Headers and cookies are a good example of this: they simply tag along for the
ride. Rocket makes retrieving and validating such information easy: simply add
any number of parameters to the request handler with types that implement the
[FromRequest](https://api.rocket.rs/rocket/request/trait.FromRequest.html)
trait. If the data can be retrieved from the incoming request and validated, the
handler is called. If it cannot, the handler isn't called, and the request is
forwarded or terminated. In this way, these parameters act as _guards_: they
protect the request handler from being called erroneously.
For example, to retrieve cookies and the Content-Type header from a request, we
can declare a route as follows:
```rust
#[get("/")]
fn index(cookies: &Cookies, content: ContentType) -> String { ... }
```
The [cookies example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/cookies)
illustrates how to use the `Cookies` type to get and set cookies.
You can implement `FromRequest` for your own types. For instance, to protect a
`sensitive` route from running unless an `APIKey` is present in the request
headers, you might create an `APIKey` type that implements `FromRequest` and use
it as a request guard:
```rust
#[get("/sensitive")]
fn sensitive(key: APIKey) -> &'static str { ... }
```
You might also implement `FromRequest` for an `AdminUser` type that validates
that the cookies in the incoming request authenticate an administrator. Then,
any handler with an `AdminUser` or `APIKey` type in its argument list is assured
to only be invoked if the appropriate conditions are met. Request guards
centralize policies, resulting in a simpler, safer, and more secure
applications.
## Data
At some point, your web application will need to process body data, and Rocket
makes it as simple as possible. Data processing, like much of Rocket, is type
directed. To indicate that a handler expects data, annotate it with a `data =
"<param>"` parameter, where `param` is an argument in the handler. The
argument's type must implement the
[FromData](https://api.rocket.rs/rocket/data/trait.FromData.html) trait. It
looks like this, where `T: FromData`:
```rust
#[post("/", data = "<input>")]
fn new(input: T) -> String { ... }
```
### Forms
Forms are the most common type of data handled in web applications, and Rocket
makes handling them easy. Say your application is processing a form submission
for a new todo `Task`. The form contains two fields: `complete`, a checkbox, and
`description`, a text field. You can easily handle the form request in Rocket
as follows:
```rust
#[derive(FromForm)]
struct Task {
complete: bool,
description: String,
}
#[post("/todo", data = "<task>")]
fn new(task: Form<Task>) -> String { ... }
```
The `Form` type implements the `FromData` trait as long as its generic parameter
implements the
[FromForm](https://api.rocket.rs/rocket/request/trait.FromForm.html) trait. In
the example, we've derived the `FromForm` trait automatically for the `Task`
structure. `FromForm` can be derived for any structure whose fields implement
[FromFormValue](https://api.rocket.rs/rocket/request/trait.FromFormValue.html).
If a `POST /todo` request arrives, the form data will automatically be parsed
into the `Task` structure. If the data that arrives isn't of the correct
Content-Type, the request is forwarded. If the data doesn't parse or is simply
invalid, a customizable `400 Bad Request` error is returned. As before, a
forward or failure can be caught by using the `Option` and `Result` types.
Fields of forms can be easily validated via implementations of the
`FromFormValue` trait. For example, if you'd like to verify that some user is
over some age in a form, then you might define a new `AdultAge` type, use it as
a field in a form structure, and implement `FromFormValue` so that it only
validates integers over that age. If a form is a submitted with a bad age,
Rocket won't call a handler requiring a valid form for that structure. You can
use `Option` or `Result` types for fields to catch parse failures.
The [forms](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/forms)
and [forms kitchen
sink](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/form_kitchen_sink)
examples on GitHub provide further illustrations.
### JSON
Handling JSON data is no harder: simply use the
[JSON](https://api.rocket.rs/rocket_contrib/struct.JSON.html) type:
```rust
#[derive(Deserialize)]
struct Task {
description: String,
complete: bool
}
#[post("/todo", data = "<task>")]
fn new(task: JSON<Task>) -> String { ... }
```
The only condition is that the generic type to `JSON` implements the
`Deserialize` trait. See the [JSON example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/json) for a
complete example.
### Streaming
Sometimes you just want to handle the incoming data directly. For example, you
might want to stream the incoming data out to a file. Rocket makes this as
simple as possible via the
[Data](https://api.rocket.rs/rocket/data/struct.Data.html) type:
```rust
#[post("/upload", format = "text/plain", data = "<data>")]
fn upload(data: Data) -> io::Result<Plain<String>> {
data.stream_to_file("/tmp/upload.txt").map(|n| Plain(n.to_string()))
}
```
The route above accepts any `POST` request to the `/upload` path with
`Content-Type` `text/plain` The incoming data is streamed out to
`tmp/upload.txt` file, and the number of bytes written is returned as a plain
text response if the upload succeeds. If the upload fails, an error response is
returned. The handler above is complete. It really is that simple! See the
[GitHub example
code](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/raw_upload)
for the full crate.
## Query Strings
Query strings are handled similarly to `POST` forms. A query string can be
parsed into any structure that implements the `FromForm` trait. They are matched
against by appending a `?` followed by a dynamic parameter `<param>` to the
path.
For instance, say you change your mind and decide to use query strings instead
of `POST` forms for new todo tasks in the previous forms example, reproduced
below:
```rust
#[derive(FromForm)]
struct Task { .. }
#[post("/todo", data = "<task>")]
fn new(task: Form<Task>) -> String { ... }
```
Rocket makes the transition simple: simply declare `<task>` as a query parameter
as follows:
```rust
#[get("/todo?<task>")]
fn new(task: Task) -> String { ... }
```
Rocket will parse the query string into the `Task` structure automatically by
matching the structure field names to the query parameters. If the parse fails,
the request is forwarded to the next matching route. To catch parse failures,
you can use `Option` or `Result` as the type of the field to catch errors for.
See [the GitHub
example](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/query_params)
for a complete illustration.
## Error Catchers
When Rocket wants to return an error page to the client, Rocket invokes the
_catcher_ for that error. A catcher is like a route, except it only handles
errors. Catchers are declared via the `error` attribute, which takes a single
integer corresponding to the HTTP status code to catch. For instance, to declare
a catcher for **404** errors, you'd write:
```rust
#[error(404)]
fn not_found(req: &Request) -> String { }
```
As with routes, Rocket needs to know about a catcher before it is used to handle
errors. The process is similar to mounting: call the `catch` method with a list
of catchers via the `errors!` macro. The invocation to add the **404** catcher
declared above looks like this:
```rust
rocket::ignite().catch(errors![not_found])
```
Unlike request handlers, error handlers can only take 0, 1, or 2 parameters of
types [Request](https://api.rocket.rs/rocket/struct.Request.html) and/or
[Error](https://api.rocket.rs/rocket/enum.Error.html). At present, the `Error`
type is not particularly useful, and so it is often omitted. The
[error catcher
example](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/errors) on
GitHub illustrates their use in full.
Rocket has a default catcher for all of the standard HTTP error codes including
**404**, **500**, and more.

169
site/guide/responses.md Normal file
View File

@ -0,0 +1,169 @@
# Responses
You may have noticed that the return type of a handler appears to be arbitrary,
and that's because it is! A value of any type that implements the
[Responder](https://api.rocket.rs/rocket/response/trait.Responder.html) trait
can be returned, including your own.
## Responder
Types that implement `Responder` know how to generate a
[Response](https://api.rocket.rs/rocket/response/struct.Response.html) from
their values. A `Response` includes the HTTP status, headers, and body of the
response. Rocket implements `Responder` for many built-in types including
`String`, `&str`, `File`, `Option`, `Result`, and others. Rocket also provides
custom types, such as
[Content](https://api.rocket.rs/rocket/response/struct.Content.html) and
[Flash](https://api.rocket.rs/rocket/response/struct.Flash.html), which you can
find in the [response](https://api.rocket.rs/rocket/response/index.html) module.
The body of a `Response` may either be _fixed-sized_ or _streaming_. The given
`Responder` implementation decides which to use. For instance, `String` uses a
fixed-sized body, while `File` uses a streaming body.
### Wrapping
Responders can _wrap_ other responders. That is, responders can be of the
following form, where `R: Responder`:
```rust
struct WrappingResponder<R>(R);
```
When this is the case, the wrapping responder will modify the response returned
by `R` in some way before responding itself. For instance, to override the
status code of some response, you can use the types in the [status
module](https://api.rocket.rs/rocket/response/status/index.html). In particular,
to set the status code of a response for a `String` to **202 Accepted**, you can
return a type of `status::Accepted<String>`:
```rust
#[get("/")]
fn accept() -> status::Accepted<String> {
status::Accepted(Some("I accept!".to_string()))
}
```
By default, the `String` responder sets the status to **200**. By using the
`Accepted` type however, The client will receive an HTTP response with status
code **202**.
Similarly, the types in the [content
module](https://api.rocket.rs/rocket/response/content/index.html) can be used to
override the Content-Type of the response. For instance, to set the Content-Type
of some `&'static str` to JSON, you can use the
[content::JSON](https://api.rocket.rs/rocket/response/content/struct.JSON.html)
type as follows:
```rust
#[get("/")]
fn json() -> content::JSON<&'static str> {
content::JSON("{ 'hi': 'world' }")
}
```
## Errors
Responders need not _always_ generate a response. Instead, they can return an
`Err` with a given status code. When this happens, Rocket forwards the request
to the error catcher for the given status code. If none exists, which can only
happen when using custom status codes, Rocket uses the **500** error catcher.
### Result
`Result` is one of the most commonly used responders. Returning a `Result` means
one of two things. If the error type implements `Responder`, the `Ok` or `Err`
value will be used, whichever the variant is. If the error type does _not_
implement `Responder`, the error is printed to the console, and the request is
forwarded to the **500** error catcher.
### Option
`Option` is another commonly used responder. If the `Option` is `Some`, the
wrapped responder is used to respond to the client. Otherwise, the request is
forwarded to the **404** error catcher.
### Failure
While not encouraged, you can also forward a request to a catcher manually by
using the [Failure](https://api.rocket.rs/rocket/response/struct.Failure.html)
type. For instance, to forward to the catcher for **406 Not Acceptable**, you
would write:
```rust
#[get("/")]
fn just_fail() -> Failure {
Failure(Status::NotAcceptable)
}
```
## JSON
Responding with JSON data is simple: return a value of type
[JSON](https://api.rocket.rs/rocket_contrib/struct.JSON.html). For example, to
respond with the JSON value of the `Task` structure from previous examples, we
would write:
```rust
#[derive(Serialize)]
struct Task { ... }
#[get("/todo")]
fn todo() -> JSON<Task> { ... }
```
The generic type in `JSON` must implement `Serialize`. The `JSON` type
serializes the structure into JSON, sets the Content-Type to JSON, and emits the
serialization in a fixed-sized body. If serialization fails, the request is
forwarded to the **500** error catcher.
For a complete example, see the [JSON example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/json).
## Templates
Rocket has built-in support for templating. To respond with a rendered template,
simply return a
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html) type.
```rust
#[get("/")]
fn index() -> Template {
let context = /* object-like value */;
Template::render("index", &context)
}
```
Templates are rendered with the `render` method. The method takes in the name of
a template and a context to render the template with. Rocket searches for a
template with that name in the configurable `template_dir` configuration
parameter, which defaults to `templates/`. Templating support in Rocket is
engine agnostic. The engine used to render a template depends on the template
file's extension. For example, if a file ends with `.hbs`, Handlebars is used,
while if a file ends with `.tera`, Tera is used.
The context can be any type that implements `Serialize` and serializes to an
`Object` value, such as structs, `HashMaps`, and others. The
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html) API
documentation contains more information about templates, while the [Handlebars
Templates example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/handlebars_templates)
is a fully composed application that makes use of Handlebars templates.
## Streaming
When a large amount of data needs to be sent to the client, it is better to
stream the data to the client to avoid consuming large amounts of memory. Rocket
provides the [Stream](https://api.rocket.rs/rocket/response/struct.Stream.html)
type, making this easy. The `Stream` type can be created from any `Read` type.
For example, to stream from a local Unix stream, we might write:
```rust
#[get("/stream")]
fn stream() -> io::Result<Stream<UnixStream>> {
UnixStream::connect("/path/to/my/socket").map(|s| Stream::from(s))
}
```
Rocket takes care of the rest.

144
site/guide/state.md Normal file
View File

@ -0,0 +1,144 @@
# State
Many web applications have a need to maintain state. This can be as simple as
maintaining a counter for the number of visits or as complex as needing to
access job queues and multiple databases. Rocket provides the tools to enable
these kinds of interactions in a safe and simple manner.
## Managed State
The enabling feature for maintaining state is _managed state_. Managed state, as
the name implies, is state that Rocket manages for your application. The state
is managed on a per-type basis: Rocket will manage at most one value of a given
type.
The process for using managed state is simple:
1. Call `manage` on the `Rocket` instance corresponding to your application
with the initial value of the state.
2. Add a `State<T>` type to any request handler, where `T` is the type of the
value passed into `manage`.
### Adding State
To instruct Rocket to manage state for your application, call the
[manage](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage) method
on a `Rocket` instance. For example, to ask Rocket to manage a `HitCount`
structure with an internal `AtomicUsize` with an initial value of `0`, we can
write the following:
```rust
struct HitCount(AtomicUsize);
rocket::ignite().manage(HitCount(AtomicUsize::new(0)));
```
The `manage` method can be called any number of times as long as each call
refers to a value of a different type. For instance, to have Rocket manage both
a `HitCount` value and a `Config` value, we can write:
```rust
rocket::ignite()
.manage(HitCount(AtomicUsize::new(0)))
.manage(Config::from(user_input));
```
### Retrieving State
State that is being managed by Rocket can be retrieved via the
[State](https://api.rocket.rs/rocket/struct.State.html) type: a [request
guard](/guide/requests/#request-guards) for managed state. To use the request
guard, add a `State<T>` type to any request handler, where `T` is the
type of the managed state. For example, we can retrieve and respond with the
current `HitCount` in a `count` route as follows:
```rust
#[get("/count")]
fn count(count: State<HitCount>) -> String {
let current_count = hit_count.0.load(Ordering::Relaxed);
format!("Number of visits: {}", current_count)
}
```
You can retrieve more than one `State` type in a single route as well:
```rust
#[get("/state")]
fn state(count: State<HitCount>, config: State<Config>) -> T { ... }
```
It can also be useful to retrieve managed state from a `FromRequest`
implementation. To do so, invoke the `from_request` method of a `State<T>` type
directly, passing in the `req` parameter of `from_request`:
```rust
fn from_request(req: &'a Request<'r>) -> request::Outcome<T, ()> {
let count = match <State<HitCount> as FromRequest>::from_request(req) {
Outcome::Success(count) => count,
...
};
...
}
```
### Unmanaged State
If you request a `State<T>` for a `T` that is not `managed`, Rocket won't call
the offending route. Instead, Rocket will log an error message and return a
**500** error to the client.
While this behavior is 100% safe, it isn't fun to return **500** errors to
clients, especially when the issue can be easily avoided. Because of this,
Rocket tries to prevent an application with unmanaged state from ever running
via the `unmanaged_state` lint. The lint reads through your code at compile-time
and emits a warning when a `State<T>` request guard is being used in a mounted
route for a type `T` that isn't being managed.
As an example, consider the following short application using our `HitCount`
type from previous examples:
```rust
#[get("/count")]
fn count(count: State<HitCount>) -> String {
let current_count = hit_count.0.load(Ordering::Relaxed);
format!("Number of visits: {}", current_count)
}
fn main() {
rocket::ignite()
.manage(Config::from(user_input))
.launch()
}
```
The application is buggy: a value for `HitCount` isn't being `managed`, but a
`State<HitCount>` type is being requested in the `count` route. When we compile
this application, Rocket emits the following warning:
```rust
warning: HitCount is not currently being managed by Rocket
--> src/main.rs:2:17
|
2 | fn count(count: State<HitCount>) -> String {
| ^^^^^^^^^^^^^^^
|
= note: this State request guard will always fail
help: maybe add a call to 'manage' here?
--> src/main.rs:8:5
|
8 | rocket::ignite()
| ^^^^^^^^^^^^^^^^
```
The `unmanaged_state` lint isn't perfect. In particular, it cannot track calls
to `manage` across function boundaries. You can disable the lint on a per-route
basis by adding `#[allow(unmanaged_state)]` to a route handler. If you wish to
disable the lint globally, add `#![allow(unmanaged_state)]` to your crate
attributes.
You can find a complete example using the `HitCounter` structure in the [state
example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/state) and
learn more about the [manage
method](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage) and
[State type](https://api.rocket.rs/rocket/struct.State.html) in the API docs.

136
site/guide/testing.md Normal file
View File

@ -0,0 +1,136 @@
# Testing
Every application should be well tested. Rocket provides the tools to perform
unit and integration tests on your application as well as inspect Rocket
generated code.
## Tests
Rocket includes a built-in [testing](https://api.rocket.rs/rocket/testing/)
module that allows you to unit and integration test your Rocket applications.
Testing is simple:
1. Construct a `Rocket` instance.
2. Construct a `MockRequest`.
3. Dispatch the request using the `Rocket` instance.
4. Inspect, validate, and verify the `Response`.
After setting up, we'll walk through each of these steps for the "Hello, world!"
program below:
```rust
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/")]
fn hello() -> &'static str {
"Hello, world!"
}
```
### Setting Up
For the `testing` module to be available, Rocket needs to be compiled with the
_testing_ feature enabled. Since this feature should only be enabled when your
application is compiled for testing, the recommended way to enable the _testing_
feature is via Cargo's `[dev-dependencies]` section in the `Cargo.toml` file as
follows:
```toml
[dev-dependencies]
rocket = { version = "0.2.5", features = ["testing"] }
```
With this in place, running `cargo test` will result in Cargo compiling Rocket
with the _testing_ feature, thus enabling the `testing` module.
You'll also need a `test` module with the proper imports:
```rust
#[cfg(test)]
mod test {
use super::rocket;
use rocket::testing::MockRequest;
use rocket::http::{Status, Method};
#[test]
fn hello_world() {
...
}
}
```
In the remainder of this section, we'll work on filling in the `hello_world`
testing function to ensure that the `hello` route results in a `Response` with
_"Hello, world!"_ in the body.
### Testing
We'll begin by constructing a `Rocket` instance with the `hello` route mounted
at the root path. We do this in the same way we would normally with one
exception: we need to refer to the `testing` route in the `super` namespace:
```rust
let rocket = rocket::ignite().mount("/", routes![super::hello]);
```
Next, we create a `MockRequest` that issues a `Get` request to the `"/"` path:
```rust
let mut req = MockRequest::new(Method::Get, "/");
```
We now ask Rocket to perform a full dispatch, which includes routing,
pre-processing and post-processing, and retrieve the `Response`:
```rust
let mut response = req.dispatch_with(&rocket);
```
Finally, we can test the
[Response](https://api.rocket.rs/rocket/struct.Response.html) values to ensure
that it contains the information we expect it to. We want to ensure two things:
1. The status is `200 OK`.
2. The body is the string "Hello, world!".
We do this by querying the `Response` object directly:
```rust
assert_eq!(response.status(), Status::Ok);
let body_str = response.body().and_then(|b| b.into_string());
assert_eq!(body_str, Some("Hello, world!".to_string()));
```
That's it! Run the tests with `cargo test`. The complete application, with
testing, can be found in the [GitHub testing
example](https://github.com/SergioBenitez/Rocket/tree/v0.2.5/examples/testing).
## Codegen Debug
It is sometimes useful to inspect the code that Rocket's code generation is
emitting, especially when you get a strange type error. To have Rocket log the
code that it is emitting to the console, set the `ROCKET_CODEGEN_DEBUG`
environment variable when compiling:
```rust
ROCKET_CODEGEN_DEBUG=1 cargo build
```
During compilation, you should see output like this:
```rust
Emitting item:
fn rocket_route_fn_hello<'_b>(_req: &'_b ::rocket::Request,
_data: ::rocket::Data)
-> ::rocket::handler::Outcome<'_b> {
let responder = hello();
::rocket::handler::Outcome::of(responder)
}
```
This corresponds to the facade request handler Rocket generated for the `hello`
route.

193
site/index.toml Normal file
View File

@ -0,0 +1,193 @@
###############################################################################
# Top features: displayed in the header under the introductory text.
###############################################################################
[release]
url = "https://crates.io/crates/rocket"
version = "0.2.5"
date = "Apr 16, 2017"
[[top_features]]
title = "Type Safe"
text = "From request to response Rocket ensures that your types mean something."
image = "helmet"
button = "Learn More"
url = "/overview/#how-rocket-works"
[[top_features]]
title = "Boilerplate Free"
text = "Spend your time writing code that really matters, and let Rocket generate the rest."
image = "robot-free"
button = "See Examples"
url = "/overview/#anatomy-of-a-rocket-application"
[[top_features]]
title = "Easy To Use"
text = "Rocket makes extensive use of Rust's code generation tools to provide a clean API."
image = "sun"
button = "Get Started"
url = "/guide"
margin = 2
[[top_features]]
title = "Extensible"
text = "Easily create your own primitives that any Rocket application can use."
image = "telescope"
button = "See How"
url = "/overview/#anatomy-of-a-rocket-application"
margin = 9
###############################################################################
# Sections: make sure there are an odd number so colors work out.
###############################################################################
[[sections]]
title = "Hello, Rocket!"
code = '''
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
fn main() {
rocket::ignite().mount("/", routes![hello]).launch();
}
'''
text = '''
This is a **complete Rocket application**. It does exactly what you would
expect. If you were to visit **http://localhost:8000/hello/John/58**, youd
see:
<span class="callout">Hello, 58 year old named John!</span>
If someone visits a path with an `<age>` that isnt a `u8`, Rocket doesnt
blindly call `hello`. Instead, it tries other matching routes or returns a
**404**.
'''
[[sections]]
title = "Forms? Check!"
code = '''
#[derive(FromForm)]
struct Task {
description: String,
completed: bool
}
#[post("/", data = "<task>")]
fn new(task: Form<Task>) -> Flash<Redirect> {
if task.get().description.is_empty() {
Flash::error(Redirect::to("/"), "Cannot be empty.")
} else {
Flash::success(Redirect::to("/"), "Task added.")
}
}
'''
text = '''
Handling forms **is simple and easy**. Simply derive `FromForm` for your
structure and let Rocket know which parameter to use. Rocket **parses and
validates** the form request, creates the structure, and calls your function.
Bad form request? Rocket doesnt call your function! What if you want to know
if the form was bad? Simple! Change the type of `task` to `Option` or
`Result`!
'''
[[sections]]
title = "JSON, out of the box."
code = '''
#[derive(Serialize, Deserialize)]
struct Message {
contents: String,
}
#[put("/<id>", data = "<message>")]
fn update(id: ID, message: JSON<Message>) -> JSON<Value> {
if DB.contains_key(&id) {
DB.insert(id, &message.contents);
JSON(json!{ "status": "ok" })
} else {
JSON(json!{ "status": "error" })
}
}
'''
text = '''
Rocket has first-class support for JSON, right out of the box. Simply derive
`Deserialize` or `Serialize` to receive or return JSON, respectively.
Like other important features, JSON works through Rockets `FromData` trait,
Rockets approach to deriving types from body data. It works like this:
specify a `data` route parameter of any type that implements `FromData`. A
value of that type will then be created automatically from the incoming
request body. Best of all, you can implement `FromData` for your types!
'''
###############################################################################
# Buttom features: displayed above the footer.
###############################################################################
[[bottom_features]]
title = 'Templating'
text = "Rocket makes rendering templates a breeze with built-in templating support."
image = 'templating-icon'
url = '/guide/responses/#templates'
button = 'Learn More'
color = 'blue'
[[bottom_features]]
title = 'Cookies'
text = "Cookies are first-class in Rocket. View, add, or remove cookies without hassle."
image = 'cookies-icon'
url = '/guide/requests/#request-guards'
button = 'Learn More'
color = 'purple'
margin = -6
[[bottom_features]]
title = 'Streams'
text = "Rocket streams all incoming and outgoing data, so size isn't a concern."
image = 'streams-icon'
url = '/guide/requests/#streaming'
button = 'Learn More'
color = 'red'
margin = -29
[[bottom_features]]
title = 'Config Environments'
text = "Configure your application your way for development, staging, and production."
image = 'config-icon'
url = '/guide/overview/#configuration'
button = 'Learn More'
color = 'yellow'
margin = -3
[[bottom_features]]
title = 'Query Params'
text = "Handling query parameters isnt an afterthought in Rocket."
image = 'query-icon'
url = '/guide/requests/#query-strings'
button = 'Learn More'
color = 'orange'
margin = -3
[[bottom_features]]
title = 'Testing Library'
text = "Unit test your applications with ease using the built-in testing library."
image = 'testing-icon'
url = '/guide/testing#testing'
button = 'Learn More'
color = 'green'
# Blocked on Hyper/OpenSSL.
# [[bottom_features]]
# title = 'Signed Sessions'
# text = "Safe, secure, signed sessions are built-in to Rocket so your users can stay safe."
# image = 'sessions-icon'
# url = '/overview'
# button = 'Learn More'
# color = 'green'

15
site/news.toml Normal file
View File

@ -0,0 +1,15 @@
[[articles]]
title = "Rocket v0.2: Managed State & More"
date = "February 06, 2017"
snippet = """
Today marks the first major release since Rocket's debut a little over a month
ago. Rocket v0.2 packs a ton of new features, fixes, and general improvements.
Much of the development in v0.2 was led by the community, either through reports
via the [GitHub issue tracker](https://github.com/SergioBenitez/Rocket/issues)
or via direct contributions. In fact, there have been **20 unique contributors**
to Rocket's code since Rocket's initial introduction! Community feedback has
been incredible. As a special thank you, we include the names of these
contributors at the end of this article.
"""
slug = "2017-02-06-version-0.2"

View File

@ -0,0 +1,392 @@
# Rocket v0.2: Managed State & More
**Posted by [Sergio Benitez](https://sergio.bz) on February 06, 2017**
Today marks the first major release since Rocket's debut a little over a month
ago. Rocket v0.2 packs a ton of new features, fixes, and general improvements.
Much of the development in v0.2 was led by the community, either through reports
via the [GitHub issue tracker](https://github.com/SergioBenitez/Rocket/issues)
or via direct contributions. In fact, there have been **20 unique contributors**
to Rocket's codebase since Rocket's initial introduction! Community feedback has
been incredible. As a special thank you, we include the names of these
contributors at the end of this article.
## About Rocket
Rocket is a web framework for Rust with a focus on ease of use, expressibility,
and speed. Rocket makes it simple to write fast web applications without
sacrificing flexibility or type safety. All with minimal code.
> Rocket's so simple, you feel like you're doing something wrong. It's like if
> you're making fire with rocks and suddently someone gives you a lighter. Even
> though you know the lighter makes fire, and does it even faster and better and
> with a simple flick, the rock's still in your brain.
>
> -- <cite>Artem "impowski" Biryukov, January 17, 2017, on **#rocket**</cite>
## New Features
Rocket v0.2 includes several new features that make developing Rocket
applications simpler, faster, and safer than ever before.
### Managed State
Undoubtedly, the star feature of this release is **managed state**. Managed
state allows you to pass state to Rocket prior to launching your application and
later retrieve that state from any request handler by simply including the
state's type in the function signature. It works in two easy steps:
1. Call `manage` on the `Rocket` instance corresponding to your application
with the initial value of the state.
2. Add a `State<T>` type to any request handler, where `T` is the type of the
value passed into `manage`.
Rocket takes care of the rest! `State` works through Rocket's [request
guards](/guide/requests/#request-guards). You can call `manage` any number of
times, as long as each call corresponds to a value of a different type.
As a simple example, consider the following "hit counter" example application:
```rust
struct HitCount(AtomicUsize);
#[get("/")]
fn index(hit_count: State<HitCount>) -> &'static str {
hit_count.0.fetch_add(1, Ordering::Relaxed);
"Your visit has been recorded!"
}
#[get("/count")]
fn count(hit_count: State<HitCount>) -> String {
hit_count.0.load(Ordering::Relaxed).to_string()
}
fn main() {
rocket::ignite()
.mount("/", routes![index, count])
.manage(HitCount(AtomicUsize::new(0)))
.launch()
}
```
Visiting `/` will record a visit by incrementing the hit count by 1. Visiting
the `/count` path will display the current hit count.
One concern when using _managed state_ is that you might forget to call `manage`
with some state's value before launching your application. Not to worry: Rocket
has your back! Let's imagine for a second that we forgot to add the call to
`manage` on line 17 in the example above. Here's what the compiler would emit
when we compile our buggy application:
```rust
warning: HitCount is not currently being managed by Rocket
--> src/main.rs:4:21
|
4 | fn index(hit_count: State<HitCount>) -> &'static str {
| ^^^^^^^^^^^^^^^
|
= note: this State request guard will always fail
help: maybe add a call to 'manage' here?
--> src/main.rs:15:5
|
15| rocket::ignite()
| ^^^^^^^^^^^^^^^^
warning: HitCount is not currently being managed by Rocket
--> src/main.rs:10:21
|
10 | fn count(hit_count: State<HitCount>) -> String {
| ^^^^^^^^^^^^^^^
|
= note: this State request guard will always fail
help: maybe add a call to 'manage' here?
--> src/main.rs:15:5
|
15 | rocket::ignite()
| ^^^^^^^^^^^^^^^^
```
You can read more about managed state in the [guide](/guide/state/), the API
docs for
[manage](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage), and the
API docs for [State](https://api.rocket.rs/rocket/struct.State.html).
### Unmounted Routes Lint
A common mistake that new Rocketeers make is forgetting to
[mount](/guide/overview/#mounting) declared routes. In Rocket v0.2, Rocket adds
a _lint_ that results in a compile-time warning for unmounted routes. As a
simple illustration, consider the canonical "Hello, world!" Rocket application
below, and note that we've forgotten to mount the `hello` route:
```rust
#[get("/")]
fn hello() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().launch();
}
```
When this program is compiled, the compiler emits the following warning:
```rust
warning: the 'hello' route is not mounted
--> src/main.rs:2:1
|
2 | fn hello() -> &'static str {
| _^ starting here...
3 | | "Hello, world!"
4 | | }
| |_^ ...ending here
|
= note: Rocket will not dispatch requests to unmounted routes.
help: maybe add a call to 'mount' here?
--> src/main.rs:7:5
|
7 | rocket::ignite().launch();
| ^^^^^^^^^^^^^^^^
```
The lint can be disabled selectively per route by adding an
`#[allow(unmounted_route)]` annotation to a given route declaration. It can also
be disabled globally by adding `#![allow(unmounted_route)]`. You can read more
about this lint in the [codegen
documentation](https://api.rocket.rs/rocket_codegen/index.html).
### Configuration via Environment Variables
A new feature that makes deploying Rocket apps to the cloud a little easier is
configuration via environment variables. Simply put, any configuration parameter
can be set via an environment variable of the form `ROCKET_{PARAM}`, where
`{PARAM}` is the name of the configuration parameter. For example, to set the
`port` Rocket listens on, simply set the `ROCKET_PORT` environment variable:
```sh
ROCKET_PORT=3000 cargo run --release
```
Configuration parameters set via environment variables take precedence over
parameters set via the `Rocket.toml` configuration file. Note that _any_
parameter can be set via an environment variable, include _extras_. For more
about configuration in Rocket, see the [configuration section of the
guide](/guide/overview/#configuration).
### And Plenty More!
Rocket v0.2 is full of many new features! In addition to the three features
described above, v0.2 also includes the following:
* `Config` structures can be built via `ConfigBuilder`, which follows the
builder pattern.
* Logging can be enabled or disabled on custom configuration via a second
parameter to the `Rocket::custom` method.
* `name` and `value` methods were added to `Header` to retrieve the name and
value of a header.
* A new configuration parameter, `workers`, can be used to set the number of
threads Rocket uses.
* The address of the remote connection is available via `Request.remote()`.
Request preprocessing overrides remote IP with value from the `X-Real-IP`
header, if present.
* During testing, the remote address can be set via `MockRequest.remote()`.
* The `SocketAddr` request guard retrieves the remote address.
* A `UUID` type has been added to `contrib`.
* `rocket` and `rocket_codegen` will refuse to build with an incompatible
nightly version and emit nice error messages.
* Major performance and usability improvements were upstreamed to the `cookie`
crate, including the addition of a `CookieBuilder`.
* When a checkbox isn't present in a form, `bool` types in a `FromForm`
structure will parse as `false`.
* The `FormItems` iterator can be queried for a complete parse via `completed`
and `exhausted`.
* Routes for `OPTIONS` requests can be declared via the `options` decorator.
* Strings can be percent-encoded via `URI::percent_encode()`.
## Breaking Changes
This release includes several breaking changes. These changes are listed below
along with a short note about how to handle the breaking change in existing
applications.
* **`Rocket::custom` takes two parameters, the first being `Config` by
value.**
A call in v0.1 of the form `Rocket::custom(&config)` is now
`Rocket::custom(config, false)`.
* **Tera templates are named without their extension.**
A templated named `name.html.tera` is now simply `name`.
* **`JSON` `unwrap` method has been renamed to `into_inner`.**
A call to `.unwrap()` should be changed to `.into_inner()`.
* **The `map!` macro was removed in favor of the `json!` macro.**
A call of the form `map!{ "a" => b }` can be written as: `json!({ "a": b
})`.
* **The `hyper::SetCookie` header is no longer exported.**
Use the `Cookie` type as an `Into<Header>` type directly.
* **The `Content-Type` for `String` is now `text/plain`.**
Use `content::HTML<String>` for HTML-based `String` responses.
* **`Request.content_type()` returns an `Option<ContentType>`.**
Use `.unwrap_or(ContentType::Any)` to get the old behavior.
* **The `ContentType` request guard forwards when the request has no
`Content-Type` header.**
Use an `Option<ContentType>` and `.unwrap_or(ContentType::Any)` for the old
behavior.
* **A `Rocket` instance must be declared _before_ a `MockRequest`.**
Change the order of the `rocket::ignite()` and `MockRequest::new()` calls.
* **A route with `format` specified only matches requests with the same
format.**
Previously, a route with a `format` would match requests without a format
specified. There is no workaround to this change; simply specify formats
when required.
* **`FormItems` can no longer be constructed directly.**
Instead of constructing as `FormItems(string)`, construct as
`FormItems::from(string)`.
* **`from_from_string(&str)` in `FromForm` removed in favor of
`from_form_items(&mut FormItems)`.**
Most implementation should be using `FormItems` internally; simply use the
passed in `FormItems`. In other cases, the form string can be retrieved via
the `inner_str` method of `FormItems`.
* **`Config::{set, default_for}` are deprecated.**
Use the `set_{param}` methods instead of `set`, and `new` or `build` in
place of `default_for`.
* **Route paths must be absolute.**
Prepend a `/` to convert a relative path into an absolute one.
* **Route paths cannot contain empty segments.**
Remove any empty segments, including trailing ones, from a route path.
## Bug Fixes
Three bugs were fixed in this release:
* Handlebars partials were not properly registered
([#122](https://github.com/SergioBenitez/Rocket/issues/122)).
* `Rocket::custom` did not set the custom configuration as the `active`
configuration.
* Route path segments with more than one dynamic parameter were erroneously
allowed.
## General Improvements
In addition to new features, Rocket saw the following smaller improvements:
* Rocket no longer overwrites a catcher's response status.
* The `port` `Config` type is now a proper `u16`.
* Clippy issues injected by codegen are resolved.
* Handlebars was updated to `0.25`.
* The `PartialEq` implementation of `Config` doesn't consider the path or
session key.
* Hyper dependency updated to `0.10`.
* The `Error` type for `JSON as FromData` has been exposed as `SerdeError`.
* SVG was added as a known Content-Type.
* Serde was updated to `0.9`.
* Form parse failure now results in a **422** error code.
* Tera has been updated to `0.7`.
* `pub(crate)` is used throughout to enforce visibility rules.
* Query parameters in routes (`/path?<param>`) are now logged.
* Routes with and without query parameters no longer _collide_.
Rocket v0.2 also includes all of the new features, bug fixes, and improvements
from versions 0.1.1 through 0.1.6. You can read more about these changes in the
[v0.1
CHANGELOG](https://github.com/SergioBenitez/Rocket/blob/v0.1/CHANGELOG.md).
## What's next?
Work now begins on Rocket v0.3! The focus of the next major release will be on
security. In particular, three major security features are planned:
1. **Automatic CSRF protection across all payload-based requests
([#14](https://github.com/SergioBenitez/Rocket/issues/14)).**
Rocket will automatically check the origin of requests made for HTTP `PUT`,
`POST`, `DELETE`, and `PATCH` requests, allowing only authorized requests to
be dispatched. This includes checking `POST`s from form submissions and any
requests made via JavaScript.
2. **Encryption and signing of session-based cookies
([#20](https://github.com/SergioBenitez/Rocket/issues/20)).**
Built-in session support will encrypt and sign cookies using a user supplied
`session_key`. Encryption and signing will occur automatically for
session-based cookies.
3. **Explicit typing of raw HTTP data strings
([#43](https://github.com/SergioBenitez/Rocket/issues/43)).**
A present, the standard `&str` type is used to represent raw HTTP data
strings. In the next release, a new type, `&RawStr`, will be used for this
purpose. This will make it clear when raw data is being handled. The type
will expose convenient methods such as `.url_decode()` and `.html_escape()`.
Work on Rocket v0.3 will also involve exploring built-in support for user
authentication and authorization as well as automatic parsing of multipart
forms.
## Contributors to v0.2
The following wonderful people helped make Rocket v0.2 happen:
<ul class="columns">
<li>Cliff H</li>
<li>Dru Sellers</li>
<li>Eijebong</li>
<li>Eric D. Reichert</li>
<li>Ernestas Poskus</li>
<li>FliegendeWurst</li>
<li>Garrett Squire</li>
<li>Giovanni Capuano</li>
<li>Greg Edwards</li>
<li>Joel Roller</li>
<li>Josh Holmer</li>
<li>Liigo Zhuang</li>
<li>Lori Holden</li>
<li>Marcus Ball</li>
<li>Matt McCoy</li>
<li>Reilly Tucker</li>
<li>Robert Balicki</li>
<li>Sean Griffin</li>
<li>Seth Lopez</li>
<li>tborsa</li>
</ul>
Thank you all! Your contributions are greatly appreciated!
Looking to help with Rocket's development? Head over to [Rocket's
GitHub](https://github.com/SergioBenitez/Rocket#contributing) and start
contributing!
## Start using Rocket today!
Not already using Rocket? Rocket is extensively documented, making it easy for
you to start writing your web applications in Rocket! See the
[overview](/overview) or start writing code immediately by reading through [the
guide](/guide).

231
site/overview.toml Normal file
View File

@ -0,0 +1,231 @@
###############################################################################
# Panels: displayed in a tabbed arrangement.
###############################################################################
[[panels]]
name = "Routing"
checked = true
content = '''
Rocket's main task is to route incoming requests to the appropriate request
handler using your application's declared routes. Routes are declared using
Rocket's _route_ attributes. The attribute describes the requests that match the
route. The attribute is placed on top of a function that is the request handler
for that route.
As an example, consider the simple route below:
```rust
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
```
This route, named `index`, will match against incoming HTTP `GET` requests to
the `/` path, the index. The request handler returns a string. Rocket will use
the string as the body of a fully formed HTTP response.
'''
[[panels]]
name = "Dynamic Params"
content = '''
Rocket allows you to interpret segments of a request path dynamically. To
illustrate, let's use the following route:
```rust
#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
```
The `hello` route above matches two dynamic path segments declared inside
brackets in the path: `<name>` and `<age>`. _Dynamic_ means that the segment can
be _any_ value the end-user desires.
Each dynamic parameter (`name` and `age`) must have a type, here `&str` and
`u8`, respectively. Rocket will attempt to parse the string in the parameter's
position in the path into that type. The route will only be called if parsing
succeeds. To parse the string, Rocket uses the
[FromParam](https://api.rocket.rs/rocket/request/trait.FromParam.html) trait,
which you can implement for your own types!
'''
[[panels]]
name = "Handling Data"
content = '''
Request body data is handled in a special way in Rocket: via the
[FromData](https://api.rocket.rs/rocket/data/trait.FromData.html) trait. Any
type that implements `FromData` can be derived from incoming body data. To tell
Rocket that you're expecting request body data, the `data` route argument is
used with the name of the parameter in the request handler:
```rust
#[post("/login", data = "<user_form>")]
fn login(user_form: Form<UserLogin>) -> String {
// Use `user_form`, return a String.
}
```
The `login` route above says that it expects `data` of type `Form<UserLogin>` in
the `user_form` parameter. The
[Form](https://api.rocket.rs/rocket/request/struct.Form.html) type is a built-in
Rocket type that knows how to parse web forms into structures. Rocket will
automatically attempt to parse the request body into the `Form` and call the
`login` handler if parsing succeeds. Other built-in `FromData` types include
[Data](https://api.rocket.rs/rocket/struct.Data.html),
[JSON](https://api.rocket.rs/rocket_contrib/struct.JSON.html), and
[Flash](https://api.rocket.rs/rocket/response/struct.Flash.html)
'''
[[panels]]
name = "Request Guards"
content = '''
In addition to dynamic path and data parameters, request handlers can also
contain a third type of parameter: _request guards_. Request guards aren't
declared in the route attribute, and any number of them can appear in the
request handler signature.
Request guards _protect_ the handler from running unless some set of conditions
are met by the incoming request metadata. For instance, if you are writing an
API that requires sensitive calls to be accompanied by an API key in the request
header, Rocket can protect those calls via a custom `APIKey` request guard:
```rust
#[get("/sensitive")]
fn sensitive(key: APIKey) -> &'static str { ... }
```
`APIKey` protects the `sensitive` handler from running incorrectly. In order for
Rocket to call the `sensitive` handler, the `APIKey` type needs to be derived
through a
[FromRequest](https://api.rocket.rs/rocket/request/trait.FromRequest.html)
implementation, which in this case, validates the API key header. Request guards
are a powerful and unique Rocket concept; they centralize application policy and
invariants through types.
'''
[[panels]]
name = "Responders"
content = '''
The return type of a request handler can by any type that implements
[Responder](https://api.rocket.rs/rocket/response/trait.Responder.html):
```rust
#[get("/")]
fn route() -> T { ... }
```
Above, T must implement `Responder`. Rocket implements `Responder` for many of
the standard library types including `&str`, `String`, `File`, `Option`, and
`Result`. Rocket also implements custom responders such as
[Redirect](https://api.rocket.rs/rocket/response/struct.Redirect.html),
[Flash](https://api.rocket.rs/rocket/response/struct.Flash.html), and
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html).
The task of a `Reponder` is to generate a
[Response](https://api.rocket.rs/rocket/response/struct.Response.html), if
possible. `Responder`s can fail with a status code. When they do, Rocket calls
the corresponding `error` route, which can be declared as follows:
```rust
#[error(404)]
fn not_found() -> T { ... }
```
'''
[[panels]]
name = "Launching"
content = '''
Launching a Rocket application is the funnest part! For Rocket to begin
dispatching requests to routes, the routes need to be _mounted_. After mounting,
the application needs to be _launched_. These two steps, usually done in `main`,
look like:
```rust
rocket::ignite()
.mount("/base", routes![index, another])
.launch()
```
The `mount` call takes a base path and a set of routes via the `routes!` macro.
The base path (`/base` above) is prepended to the path of every route in the
list. This effectively namespaces the routes, allowing for easier composition.
The `launch` call starts the server. In development, Rocket prints useful
information to the console to let you know everything is okay.
```sh
🚀 Rocket has launched from http://localhost:8000...
```
'''
###############################################################################
# Steps to "How Rocket Works"
###############################################################################
[[steps]]
name = "Validation"
color = "blue"
content = '''
First, Rocket validates a matching request by ensuring that all of the types in
a given handler can be derived from the incoming request. If the types cannot be
derived, the request is forwarded to the next matching route until a routes
types validate or there are no more routes to try. If all routes fail, a
customizable **404** error is returned.
```rust
#[post("/user", data = "<new_user>")]
fn new_user(admin: AdminUser, new_user: Form<User>) -> T {
...
}
```
For the `new_user` handler above to be called, the following conditions must
hold:
* The request method must be `POST`.
* The request path must be `/user`.
* The request must contain `data` in its body.
* The request metadata must authenticate an `AdminUser`.
* The request body must be a form that parses into a `User` struct.
'''
[[steps]]
name = "Processing"
color = "purple"
content = '''
Next, the request is processed by an arbitrary handler. This is where most of
the business logic in an application resides, and the part of your applications
youll likely spend the most time writing. In Rocket, handlers are simply
functions - thats it! The only caveat is that the functions return type must
implement the `Responder` trait. The `new_user` function above is an example of
a handler.
'''
[[steps]]
name = "Response"
color = "red"
content = '''
Finally, Rocket responds to the client by transforming the return value of the
handler into an HTTP response. The HTTP response generated from the returned
value depends on the types specific `Responder` trait implementation.
```rust
fn route() -> T { ... }
```
If the function above is used as a handler, for instance, then the type `T` must
implement `Responder`. Rocket provides many useful responder types out of the
box. They include:
* `JSON<T>`: Serializes the structure T into JSON and returns it to
the client.
* `Template`: Renders a template file and returns it to the client.
* `Redirect`: Returns a properly formatted HTTP redirect.
* `NamedFile`: Streams a given file to the client with the
Content-Type taken from the files extension.
* `Stream`: Streams data to the client from an arbitrary `Read` value.
* Many Primitive Types: `String`, `&str`, `File`, `Option`, `Result`, and
others all implement the `Responder` trait.
'''