Skip to content

Commit 1f9ca36

Browse files
authored
add http-request.md document (code-dot-org#15043)
* add http-request doc Some notes tracing through the life of a Code.org HTTP request. Intended as a general introduction to the HTTP-request lifecycle in our codebase.
1 parent 4b1823d commit 1f9ca36

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

docs/http-request.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# The life of a `code.org` HTTP Request
2+
3+
## DNS resolution
4+
5+
`code.org` => (DNS managed by route 53) => `54.192.37.35` (...etc...)
6+
7+
(`dig code.org` => `54.192.37.35`, `whois 54.192.37.35` <sup>[output](https://gist.github.com/wjordan/1f2c60e3fec28dbef5c774f08fb3c675)</sup> shows it's an Amazon-owned IP, `AMAZO-CF2` == CloudFront.)
8+
9+
## CDN / load-balancer
10+
11+
[CloudFront](https://aws.amazon.com/cloudfront/) => [Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) [ELB]
12+
13+
ELB => => multiple Frontend servers ([Elastic Compute Cloud](https://aws.amazon.com/ec2/) [EC2] with [Auto Scaling](https://aws.amazon.com/autoscaling/))
14+
15+
## Frontend Server
16+
[Varnish Cache](https://varnish-cache.org/) (port `80`) => port `8080` (dashboard) or port `8081` (pegasus) (depending on `Host` header: `code.org` => `pegasus`, `studio.code.org` => `dashboard`)
17+
18+
[NGiNX](https://www.nginx.com/) (port `808{0,1}`) => Unix socket/s (`/run/unicorn/{dashboard,pegasus}.sock`)
19+
20+
[Unicorn](https://bogomips.org/unicorn/) (UNIX socket/s) => Ruby application Rack server/s
21+
22+
Rack server definition files:
23+
- dashboard: [`dashboard/config.ru`](https://github.com/code-dot-org/code-dot-org/blob/staging/dashboard/config.ru)
24+
- pegasus: [`pegasus/config.ru`](https://github.com/code-dot-org/code-dot-org/blob/staging/pegasus/config.ru)
25+
26+
### Pegasus web-application (`/pegasus` - [code.org](https://code.org))
27+
28+
Web-application based on [`sinatra`](http://www.sinatrarb.com/) routing framework, with custom template and view-rendering layer.
29+
- [`pegasus/router.rb`](https://github.com/code-dot-org/code-dot-org/blob/staging/pegasus/router.rb): - `class Documents < Sinatra::Base`
30+
- Additional routes are in [`pegasus/routes/*.rb`](https://github.com/code-dot-org/code-dot-org/tree/staging/pegasus/routes), which are all [recursively inserted](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L185) into the `Documents` class.
31+
- [`get_head_or_post '*'`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L200-L210) - `path` == `/` for root page request
32+
- [`resolve_document(uri)`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L380-L403) -> [`resolve_template('public', extnames, uri)`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L358-L378) - resolves a URI to a path on the filesystem ending in `/public`. A [Sinatra `before` hook](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L118-L132) sets a directory to search based on the `Host` of the request [prepended](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L247-L249) with [`sites.v3`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L80). (e.g.: `GET /` with header `Host: code.org` ultimately resolves to [`pegasus/sites.v3/code.org/public/index.haml`](https://github.com/code-dot-org/code-dot-org/blob/staging/pegasus/sites.v3/code.org/public/index.haml) on the filesystem.)
33+
- [`document path`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L273-L310) - read path from filesystem and render output
34+
- [`render_ content, extname`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L273-L310) - render content from template based on file extension
35+
- [`after do` (Sinatra `after` hook)](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L212-L238) - load and render [`layouts/`](https://github.com/code-dot-org/code-dot-org/tree/staging/pegasus/sites.v3/code.org/layouts) and [`themes/`](https://github.com/code-dot-org/code-dot-org/tree/staging/pegasus/sites.v3/code.org/themes) templates from file:
36+
- layouts and themes 'wrap' themselves around the existing rendered body through the line: [`body render_template(template, @locals.merge({body: body.join('')}))`](https://github.com/code-dot-org/code-dot-org/blob/73afd7d4ad6a485bf22cac2656670d3816fd077c/pegasus/router.rb#L229), which calls [`#body`](https://github.com/sinatra/sinatra/blob/v2.0.0/lib/sinatra/base.rb#L252-L254), which first reads (passed as a local variable to `#render_template`) and then updates the template-rendered result.
37+
38+
### Dashboard application (`/dashboard` - [studio.code.org](https://studio.code.org))
39+
40+
Standard Rails application.
41+
- [`dashboard/config/routes.rb`](https://github.com/code-dot-org/code-dot-org/blob/staging/dashboard/config/routes.rb) (run `rails routes` for fullly-rendered route map)
42+
- Uses standard Rails routing and layouts/rendering (see [Ruby on Rails Guides](http://guides.rubyonrails.org/v5.0/) for full documentation, e.g., ["Routing"](http://guides.rubyonrails.org/v5.0/routing.html) and ["Layouts and Rendering"](http://guides.rubyonrails.org/v5.0/layouts_and_rendering.html))
43+
44+
### Shared middleware (`/shared`)
45+
46+
We have several [Rack](http://rack.github.io/) middleware<sup>[spec](http://www.rubydoc.info/github/rack/rack/master/file/SPEC)</sup> modules that are inserted into both Pegasus (via [`config.ru`](https://github.com/code-dot-org/code-dot-org/blob/980e4629bc8829bd1cdc5c9f04a5b1a3010292db/pegasus/config.ru#L39-L52)) and Dashboard (via [`application.rb`](https://github.com/code-dot-org/code-dot-org/blob/2342c08cd969e05af884a42baaf38e0e5565c18e/dashboard/config/application.rb#L46-L63)), and provide 'shared' functionality to both web-applications. Some of these middleware apps are their own self-contained Sinatra apps (e.g., [`FilesApi`](https://github.com/code-dot-org/code-dot-org/blob/ceaeea0101eaf3ed5d68f63e8bcdbecd7bd46106/shared/middleware/files_api.rb#L6)) that handle their defined routes<sup>[example](https://github.com/code-dot-org/code-dot-org/blob/ceaeea0101eaf3ed5d68f63e8bcdbecd7bd46106/shared/middleware/files_api.rb#L109)</sup> when inserted into the middleware 'stack' for each web-app.

0 commit comments

Comments
 (0)