folder structure, spm, + routing

This commit is contained in:
tanner0101 2019-10-22 19:02:24 -04:00
parent d498dd5ff7
commit c6d806cf0c
6 changed files with 286 additions and 2 deletions

View File

@ -0,0 +1,81 @@
# Folder Structure
Now that you've created, built, and run your first Vapor app, let's take a moment to familiarize you with Vapor's folder structure. The structure is based on [SPM](spm.md)'s folder structure, so if you've worked with SPM before it should be familiar.
```
.
├── Public
├── Sources
│ ├── App
│ │ ├── Controllers
│ │ ├── Migrations
│ │ ├── Models
│ │ ├── app.swift
│ │ ├── configure.swift
│ │ └── routes.swift
│ └── Run
│ └── main.swift
├── Tests
│ └── AppTests
└── Package.swift
```
The sections below explain each part of the folder structure in more detail.
## Public
This folder contains any public files that will be served by your app if `FileMiddleware` is enabled. This is usually images, style sheets, and browser scripts. For example, a request to `localhost:8080/favicon.ico` will check to see if `Public/favicon.ico` exists and return it.
You will need to enable `FileMiddleware` in your `configure.swift` file before Vapor can serve public files.
```swift
// Serves files from `Public/` directory
middlewares.use(app.make(FileMiddleware.self))
```
## Sources
This folder contains all of the Swift source files for your project.
The top level folders, `App` and `Run`, reflect your package's modules,
as declared in the [SPM](spm.md) manifest.
### App
This is where all of your application logic goes.
#### Controllers
Controllers are great way of grouping together application logic. Most controllers have many functions that accept a request and return some sort of response.
#### Migrations
The migrations folder is where your database migrations go if you are using Fluent.
#### Models
The models folder is a great place to store your `Content` structs or Fluent `Model`s.
#### app.swift
This file contains the `app(_:)` function which creates a configured instance of your Vapor `Application`. This method is used by the `Run` target's `main.swift` file to create and run your application. This method is also used in tests to create an instance of your application for testing.
#### configure.swift
This file contains the `configure(_:)` function. This method is called by `app(_:)` to configure the newly created `Application`. This is where you should register services like routes, databases, providers, and more.
#### routes.swift
This file contains the `routes(_:)` function. This method is called near the end of `configure(_:)` to register routes to your `Application`.
## Tests
Each non-executable module in your `Sources` folder can have a corresponding folder in `Tests`. This contains code built on the `XCTest` module for testing your package. Tests can be run using `swift test` on the command line or pressing ⌘+U in Xcode.
### AppTests
This folder contains the unit tests for code in your `App` module.
## Package.swift
Finally is [SPM](spm.md)'s package manifest.

View File

@ -0,0 +1,104 @@
# Swift Package Manager
The [Swift Package Manager](https://swift.org/package-manager/) (SPM) is used for building your project's source code and dependencies. Since Vapor relies heavily on SPM, it's a good idea to understand the basics of how it works.
SPM is similar to Cocoapods, Ruby gems, and NPM. You can use SPM from the command line with commands like `swift build` and `swift test` or with compatible IDEs. However, unlike some other package managers, there is no central package index for SPM packages. SPM instead leverages URLs to Git repositories and versions dependencies using [Git tags](https://git-scm.com/book/en/v2/Git-Basics-Tagging).
## Package Manifest
The first place SPM looks in your project is the package manifest. This should always be located in the root directory of your project and named `Package.swift`.
Take a look at this example Package manifest.
```swift
// swift-tools-version:5.1
import PackageDescription
let package = Package(
name: "app",
platforms: [
.macOS(.v10_14)
],
products: [
.executable(name: "Run", targets: ["Run"]),
.library(name: "App", targets: ["App"]),
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
],
targets: [
.target(name: "App", dependencies: ["Fluent"]),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App"])
]
)
```
Each part of the manifest is explained in the following sections.
### Tools Version
The very first line of a package manifest indicates the Swift tools version required. This specifies the minimum version of Swift that the package supports. The Package description API may also change between Swift versions, so this line ensures Swift will know how to parse your manifest.
### Package Name
The first argument to `Package` is the package's name. If the package is public, you should use the last segment of the Git repo's URL as the name.
### Platforms
The `platforms` array specifies which platforms this package supports. By specifying `.macOS(.v10_14)` this package requires macOS Mojave or greater. When Xcode loads this project, it will automatically set the minimum deployment version to 10.14 so that you can use all available APIs.
### Products
Products are targets that your package produces when built. In this package, there are two targets. A library and an executable.
### Dependencies
Dependencies are other SPM packages that your package relies on. All Vapor applications rely on the Vapor package, but you can add as many other dependencies as you want.
In the above example, you can see [vapor/vapor](https://github.com/vapor/vapor) version 4.0.0 or later is a dependency of this package. When you add a dependency to your package, you must next signal which [targets](#targets) depend on
the newly available modules.
### Targets
Targets are all of the modules, executables, and tests that your package contains. Most Vapor apps will have three targets, although you can add as many as you like to organize your code. Each target declares which modules it depends on. You must add module names here in order to import them in your code. A target can depend on other targets in your project or any modules exposed by packages you've added to
the [main dependencies](#dependencies) array.
!!! tip
Executable targets (targets that contain a `main.swift` file) cannot be imported by other modules.
This is why Vapor has both an `App` and a `Run` target.
Any code you include in `App` can be tested in the `AppTests`.
## Folder Structure
Below is the typical folder structure for an SPM package.
```
.
├── Sources
│ ├── App
│ │ └── (Source code)
│ └── Run
│ └── main.swift
├── Tests
│ └── AppTests
└── Package.swift
```
Each `.target` corresponds to a folder in the `Sources` folder.
Each `.testTarget` corresponds to a folder in the `Tests` folder.
## Package.resolved
The first time you build your project, SPM will create a `Package.resolved` file that stores the version of each dependency. The next time you build your project, these same versions will be used even if newer versions are available.
To update your depdencies, run `swift package update`.
## Xcode
If you are using Xcode 11 or greater, changes to dependencies, targets, products, etc will happen automatically whenever the `Package.swift` file is modified.
If you want to update to the latest dependencies, use File → Swift Packages → Update To Latest Swift Package Versions.
You may also want to add the `.swiftpm` file to your `.gitignore`. This is where Xcode will store your Xcode project configuration.

View File

@ -27,7 +27,7 @@ Vapor 4 requires Swift 5.1 or greater.
## Install Toolbox
Now that you have Swift installed, let's install the Vapor Toolbox. This CLI tool is not required to use Vapor but it includes helpful utilities like a new project creator.
Now that you have Swift installed, let's install the [Vapor Toolbox](https://github.com/vapor/toolbox). This CLI tool is not required to use Vapor but it includes helpful utilities like a new project creator.
Toolbox is distributed via Homebrew. If you don't have Homebrew yet, visit <a href="https://brew.sh" target="_blank">brew.sh</a> for install instructions.

View File

@ -22,7 +22,7 @@ You can also use Swift's official Docker images which come with the compiler pre
## Install Toolbox
Now that you have Swift installed, let's install the [Vapor Toolbox](../getting-started/toolbox.md). This CLI tool is not required to use Vapor, but it includes helpful utilities.
Now that you have Swift installed, let's install the [Vapor Toolbox](https://github.com/vapor/toolbox). This CLI tool is not required to use Vapor, but it includes helpful utilities.
On Linux, you will need to build the toolbox from source. View the toolbox's <a href="https://github.com/vapor/toolbox/releases" target="_blank">releases</a> on GitHub to find the latest version.

View File

@ -0,0 +1,95 @@
# Routing
Routing is the process of finding the appropriate request handler for an incoming request. At the core of Vapor's routing is a high-performance, trie-node router from [RoutingKit](https://github.com/vapor/routing-kit).
To understand how routing works in Vapor, you must first understand the basics of an HTTP request. Take a look at the following example request.
```http
GET /hello/vapor HTTP/1.1
host: vapor.codes
content-length: 0
```
This is a simple `GET` HTTP request to the URL `/hello/vapor`. This is the kind of HTTP request your browser would make if you pointed it to the following URL.
```
http://vapor.codes/hello/vapor
```
## HTTP Verb
The first part of the request is the HTTP verb. `GET` is the most common HTTP verb, but there are several you will use often. These HTTP verbs are often associated with [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) semantics.
|verb|crud|
|-|-|
|`GET`|Read|
|`POST`|Create|
|`PUT`|Replace|
|`PATCH`|Update|
|`DELETE`|Delete|
## Request Path
Right after the HTTP verb is the request's URI. This consists of a path starting with `/` and an optional query string after `?`. The HTTP verb and path are what Vapor uses to route requests.
After the HTTP verb and URI is the HTTP version followed by zero or more headers and finally a body. Since this is a `GET` request, it does not have a body.
## Router Methods
Let's take a look at how this request could be handled in Vapor.
```swift
app.get("hello", "vapor") { req in
return "Hello, vapor!"
}
```
All of the common HTTP verbs are available as methods on `Application`. They accept one or more string arguments that represent the request's path separated by `/`.
Note that you could also write this using `on` followed by the verb.
```swift
app.on(.GET, "hello", "vapor") { ... }
```
With this route registered, the example HTTP request from above will result in the following HTTP response.
```http
HTTP/1.1 200 OK
content-length: 13
content-type: text/plain; charset=utf-8
Hello, vapor!
```
## Route Parameters
Now that we've successfully routed a request based on the HTTP verb and path, let's try making the path dynamic. Notice that the name "vapor" is hardcoded in both the path and the response. Let's make this dynamic so that you can visit `/hello/<any name>` and get a response.
```swift
app.get("hello", ":name") { req -> String in
let name = req.parameters.get("name")!
return "Hello, \(name)!"
}
```
By using a path component prefixed with `:`, we indicate to the router that this is a dynamic component. Any string supplied here will now match this route. We can then use `req.parameters` to access the value of the string.
!!! tip
We can be sure that `req.parameters.get` will never return `nil` here since our route path includes `:name`. However, if you are accessing route parameters in middleware or in code triggered by multiple routes, you will want to handle the possibility of `nil`.
If you run the example request again, you'll still get a response that says hello to vapor. However, you can now include any name after `/hello/` and see it included in the response. Let's try `/hello/bob`.
```http
GET /hello/bob HTTP/1.1
content-length: 0
```
```http
HTTP/1.1 200 OK
content-length: 13
content-type: text/plain; charset=utf-8
Hello, bob!
```
Now that you understand the basics, check out each section to learn more about parameters, groups, and more.

View File

@ -31,6 +31,10 @@ nav:
- 'Ubuntu': 'install/ubuntu.md'
- 'Getting Started':
- 'Hello, world': 'getting-started/hello-world.md'
- 'Folder Structure': 'getting-started/folder-structure.md'
- 'SPM': 'getting-started/spm.md'
- 'Routing':
'Overview': 'routing/overview.md'
- 'Version (4.0)':
- '1.5': 'version/1_5.md'
- '2.0': 'version/2_0.md'