{"action":"closed","number":4,"pull_request":{"url":"https://api.github.com/repos/cybergeek94/multipart/pulls/4","id":39902005,"html_url":"https://github.com/cybergeek94/multipart/pull/4","diff_url":"https://github.com/cybergeek94/multipart/pull/4.diff","patch_url":"https://github.com/cybergeek94/multipart/pull/4.patch","issue_url":"https://api.github.com/repos/cybergeek94/multipart/issues/4","number":4,"state":"closed","locked":false,"title":"Bring `multipart` back from the dead!","user":{"login":"cybergeek94","id":3198595,"avatar_url":"https://avatars.githubusercontent.com/u/3198595?v=3","gravatar_id":"","url":"https://api.github.com/users/cybergeek94","html_url":"https://github.com/cybergeek94","followers_url":"https://api.github.com/users/cybergeek94/followers","following_url":"https://api.github.com/users/cybergeek94/following{/other_user}","gists_url":"https://api.github.com/users/cybergeek94/gists{/gist_id}","starred_url":"https://api.github.com/users/cybergeek94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cybergeek94/subscriptions","organizations_url":"https://api.github.com/users/cybergeek94/orgs","repos_url":"https://api.github.com/users/cybergeek94/repos","events_url":"https://api.github.com/users/cybergeek94/events{/privacy}","received_events_url":"https://api.github.com/users/cybergeek94/received_events","type":"User","site_admin":false},"body":"Special thanks to @LukasKalbertodt for rewriting the Travis CI script and motivating me to revive this old repo in the first place. (Will update to use GitHub Pages for docs hosting later)\r\n\r\nMassive changes, let's see if I can sum them up briefly:\r\n\r\nLibrary-wide changes:\r\n* updated to latest Rust and Hyper APIs\r\n* builds on Rust stable (!!!)\r\n* decoupled the `client` and `server` modules (previously shared data structs)\r\n* moved MIME type guessing to external crate\r\n* `hyper` integration is now optional, can support other HTTP libs in the future as well as user types\r\n    * happy consequence: now possible to mock out the HTTP backend in tests\r\n* de-cluttered `src/lib.rs` (still has some utility functions that don't really have a better place to go)\r\n* full Crates.io integration, no more Git refs\r\n* more complete documentation thanks to `#![warn(missing_docs)]`\r\n* generally improved API ergonomics\r\n\r\nClient API:\r\n* got rid of all trait objects and unnecessary allocations, now writes directly to the stream\r\n* redesigned API to support method chaining while making errors less of a pain to deal with (RFC on actual ergonomics of this design)\r\n* `Multipart` doesn't care anymore about whether the request is sized or not, except for one convenience method\r\n* eliminated most panics/asserts\r\n\r\nServer API:\r\n* `BoundaryReader` no longer reinvents the wheel WRT buffering, also probably fixed some logic errors that were hard to diagnose\r\n* nested boundaries are still not supported, but will be easier to implement and shouldn't trip up parsing if they do appear\r\n* made multipart data parsing easier to hack on by giving each header its own object responsible for it\r\n* cut out a lot of unnecessary allocations in parsing\r\n* eliminated all but one `unsafe` block (which is copied *ad verbatim* from a stdlib unstable function)\r\n\r\nThis is probably the biggest undertaking I've had in a Rust project yet. I almost lost all this work just an hour ago to a bad rebase and blind force-push, but thankfully I was able to recover the correct HEAD from the reflog. I definitely learned my lesson there. Hopefully it wasn't all for naught.\r\n\r\nCloses #2.","created_at":"2015-07-14T10:27:48Z","updated_at":"2015-07-14T21:27:00Z","closed_at":"2015-07-14T21:27:00Z","merged_at":"2015-07-14T21:27:00Z","merge_commit_sha":"9137b5441983b0bcc29cefb88b92bbe8c41c57f1","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/cybergeek94/multipart/pulls/4/commits","review_comments_url":"https://api.github.com/repos/cybergeek94/multipart/pulls/4/comments","review_comment_url":"https://api.github.com/repos/cybergeek94/multipart/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cybergeek94/multipart/issues/4/comments","statuses_url":"https://api.github.com/repos/cybergeek94/multipart/statuses/dd037a1cd6a8782b65b966d88ed1e24bfa715b43","head":{"label":"cybergeek94:revival","ref":"revival","sha":"dd037a1cd6a8782b65b966d88ed1e24bfa715b43","user":{"login":"cybergeek94","id":3198595,"avatar_url":"https://avatars.githubusercontent.com/u/3198595?v=3","gravatar_id":"","url":"https://api.github.com/users/cybergeek94","html_url":"https://github.com/cybergeek94","followers_url":"https://api.github.com/users/cybergeek94/followers","following_url":"https://api.github.com/users/cybergeek94/following{/other_user}","gists_url":"https://api.github.com/users/cybergeek94/gists{/gist_id}","starred_url":"https://api.github.com/users/cybergeek94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cybergeek94/subscriptions","organizations_url":"https://api.github.com/users/cybergeek94/orgs","repos_url":"https://api.github.com/users/cybergeek94/repos","events_url":"https://api.github.com/users/cybergeek94/events{/privacy}","received_events_url":"https://api.github.com/users/cybergeek94/received_events","type":"User","site_admin":false},"repo":{"id":25510903,"name":"multipart","full_name":"cybergeek94/multipart","owner":{"login":"cybergeek94","id":3198595,"avatar_url":"https://avatars.githubusercontent.com/u/3198595?v=3","gravatar_id":"","url":"https://api.github.com/users/cybergeek94","html_url":"https://github.com/cybergeek94","followers_url":"https://api.github.com/users/cybergeek94/followers","following_url":"https://api.github.com/users/cybergeek94/following{/other_user}","gists_url":"https://api.github.com/users/cybergeek94/gists{/gist_id}","starred_url":"https://api.github.com/users/cybergeek94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cybergeek94/subscriptions","organizations_url":"https://api.github.com/users/cybergeek94/orgs","repos_url":"https://api.github.com/users/cybergeek94/repos","events_url":"https://api.github.com/users/cybergeek94/events{/privacy}","received_events_url":"https://api.github.com/users/cybergeek94/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cybergeek94/multipart","description":"An extension to hyperium/hyper that adds support for HTTP multipart requests","fork":false,"url":"https://api.github.com/repos/cybergeek94/multipart","forks_url":"https://api.github.com/repos/cybergeek94/multipart/forks","keys_url":"https://api.github.com/repos/cybergeek94/multipart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cybergeek94/multipart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cybergeek94/multipart/teams","hooks_url":"https://api.github.com/repos/cybergeek94/multipart/hooks","issue_events_url":"https://api.github.com/repos/cybergeek94/multipart/issues/events{/number}","events_url":"https://api.github.com/repos/cybergeek94/multipart/events","assignees_url":"https://api.github.com/repos/cybergeek94/multipart/assignees{/user}","branches_url":"https://api.github.com/repos/cybergeek94/multipart/branches{/branch}","tags_url":"https://api.github.com/repos/cybergeek94/multipart/tags","blobs_url":"https://api.github.com/repos/cybergeek94/multipart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cybergeek94/multipart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cybergeek94/multipart/git/refs{/sha}","trees_url":"https://api.github.com/repos/cybergeek94/multipart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cybergeek94/multipart/statuses/{sha}","languages_url":"https://api.github.com/repos/cybergeek94/multipart/languages","stargazers_url":"https://api.github.com/repos/cybergeek94/multipart/stargazers","contributors_url":"https://api.github.com/repos/cybergeek94/multipart/contributors","subscribers_url":"https://api.github.com/repos/cybergeek94/multipart/subscribers","subscription_url":"https://api.github.com/repos/cybergeek94/multipart/subscription","commits_url":"https://api.github.com/repos/cybergeek94/multipart/commits{/sha}","git_commits_url":"https://api.github.com/repos/cybergeek94/multipart/git/commits{/sha}","comments_url":"https://api.github.com/repos/cybergeek94/multipart/comments{/number}","issue_comment_url":"https://api.github.com/repos/cybergeek94/multipart/issues/comments{/number}","contents_url":"https://api.github.com/repos/cybergeek94/multipart/contents/{+path}","compare_url":"https://api.github.com/repos/cybergeek94/multipart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cybergeek94/multipart/merges","archive_url":"https://api.github.com/repos/cybergeek94/multipart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cybergeek94/multipart/downloads","issues_url":"https://api.github.com/repos/cybergeek94/multipart/issues{/number}","pulls_url":"https://api.github.com/repos/cybergeek94/multipart/pulls{/number}","milestones_url":"https://api.github.com/repos/cybergeek94/multipart/milestones{/number}","notifications_url":"https://api.github.com/repos/cybergeek94/multipart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cybergeek94/multipart/labels{/name}","releases_url":"https://api.github.com/repos/cybergeek94/multipart/releases{/id}","created_at":"2014-10-21T08:23:42Z","updated_at":"2015-04-29T03:22:14Z","pushed_at":"2015-07-14T21:27:00Z","git_url":"git://github.com/cybergeek94/multipart.git","ssh_url":"git@github.com:cybergeek94/multipart.git","clone_url":"https://github.com/cybergeek94/multipart.git","svn_url":"https://github.com/cybergeek94/multipart","homepage":null,"size":403,"stargazers_count":3,"watchers_count":3,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":3,"default_branch":"master"}},"base":{"label":"cybergeek94:master","ref":"master","sha":"1f99c07c9383539fb220e2946af949dc0ffb2c93","user":{"login":"cybergeek94","id":3198595,"avatar_url":"https://avatars.githubusercontent.com/u/3198595?v=3","gravatar_id":"","url":"https://api.github.com/users/cybergeek94","html_url":"https://github.com/cybergeek94","followers_url":"https://api.github.com/users/cybergeek94/followers","following_url":"https://api.github.com/users/cybergeek94/following{/other_user}","gists_url":"https://api.github.com/users/cybergeek94/gists{/gist_id}","starred_url":"https://api.github.com/users/cybergeek94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cybergeek94/subscriptions","organizations_url":"https://api.github.com/users/cybergeek94/orgs","repos_url":"https://api.github.com/users/cybergeek94/repos","events_url":"https://api.github.com/users/cybergeek94/events{/privacy}","received_events_url":"https://api.github.com/users/cybergeek94/received_events","type":"User","site_admin":false},"repo":{"id":25510903,"name":"multipart","full_name":"cybergeek94/multipart","owner":{"login":"cybergeek94","id":3198595,"avatar_url":"https://avatars.githubusercontent.com/u/3198595?v=3","gravatar_id":"","url":"https://api.github.com/users/cybergeek94","html_url":"https://github.com/cybergeek94","followers_url":"https://api.github.com/users/cybergeek94/followers","following_url":"https://api.github.com/users/cybergeek94/following{/other_user}","gists_url":"https://api.github.com/users/cybergeek94/gists{/gist_id}","starred_url":"https://api.github.com/users/cybergeek94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cybergeek94/subscriptions","organizations_url":"https://api.github.com/users/cybergeek94/orgs","repos_url":"https://api.github.com/users/cybergeek94/repos","events_url":"https://api.github.com/users/cybergeek94/events{/privacy}","received_events_url":"https://api.github.com/users/cybergeek94/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cybergeek94/multipart","description":"An extension to hyperium/hyper that adds support for HTTP multipart requests","fork":false,"url":"https://api.github.com/repos/cybergeek94/multipart","forks_url":"https://api.github.com/repos/cybergeek94/multipart/forks","keys_url":"https://api.github.com/repos/cybergeek94/multipart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cybergeek94/multipart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cybergeek94/multipart/teams","hooks_url":"https://api.github.com/repos/cybergeek94/multipart/hooks","issue_events_url":"https://api.github.com/repos/cybergeek94/multipart/issues/events{/number}","events_url":"https://api.github.com/repos/cybergeek94/multipart/events","assignees_url":"https://api.github.com/repos/cybergeek94/multipart/assignees{/user}","branches_url":"https://api.github.com/repos/cybergeek94/multipart/branches{/branch}","tags_url":"https://api.github.com/repos/cybergeek94/multipart/tags","blobs_url":"https://api.github.com/repos/cybergeek94/multipart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cybergeek94/multipart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cybergeek94/multipart/git/refs{/sha}","trees_url":"https://api.github.com/repos/cybergeek94/multipart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cybergeek94/multipart/statuses/{sha}","languages_url":"https://api.github.com/repos/cybergeek94/multipart/languages","stargazers_url":"https://api.github.com/repos/cybergeek94/multipart/stargazers","contributors_url":"https://api.github.com/repos/cybergeek94/multipart/contributors","subscribers_url":"https://api.github.com/repos/cybergeek94/multipart/subscribers","subscription_url":"https://api.github.com/repos/cybergeek94/multipart/subscription","commits_url":"https://api.github.com/repos/cybergeek94/multipart/commits{/sha}","git_commits_url":"https://api.github.com/repos/cybergeek94/multipart/git/commits{/sha}","comments_url":"https://api.github.com/repos/cybergeek94/multipart/comments{/number}","issue_comment_url":"https://api.github.com/repos/cybergeek94/multipart/issues/comments{/number}","contents_url":"https://api.github.com/repos/cybergeek94/multipart/contents/{+path}","compare_url":"https://api.github.com/repos/cybergeek94/multipart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cybergeek94/multipart/merges","archive_url":"https://api.github.com/repos/cybergeek94/multipart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cybergeek94/multipart/downloads","issues_url":"https://api.github.com/repos/cybergeek94/multipart/issues{/number}","pulls_url":"https://api.github.com/repos/cybergeek94/multipart/pulls{/number}","milestones_url":"https://api.github.com/repos/cybergeek94/multipart/milestones{/number}","notifications_url":"https://api.github.com/repos/cybergeek94/multipart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cybergeek94/multipart/labels{/name}","releases_url":"https://api.github.com/repos/cybergeek94/multipart/releases{/id}","created_at":"2014-10-21T08:23:42Z","updated_at":"2015-04-29T03:22:14Z","pushed_at":"2015-07-14T21:27:00Z","git_url":"git://github.com/cybergeek94/multipart.git","ssh_url":"git@github.com:cybergeek94/multipart.git","clone_url":"https://github.com/cybergeek94/multipart.git","svn_url":"https://github.com/cybergeek94/multipart","homepage":null,"size":403,"stargazers_count":3,"watchers_count":3,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cybergeek94/multipart/pulls/4"},"html":{"href":"https://github.com/cybergeek94/multipart/pull/4"},"issue":{"href":"https://api.github.com/repos/cybergeek94/multipart/issues/4"},"comments":{"href":"https://api.github.com/repos/cybergeek94/multipart/issues/4/comments"},"review_comments":{"href":"https://api.github.com/repos/cybergeek94/multipart/pulls/4/comments"},"review_comment":{"href":"https://api.github.com/repos/cybergeek94/multipart/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cybergeek94/multipart/pulls/4/commits"},"statuses":{"href":"https://api.github.com/repos/cybergeek94/multipart/statuses/dd037a1cd6a8782b65b966d88ed1e24bfa715b43"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"cybergeek94","id":3198595,"avatar_url":"https://avatars.githubusercontent.com/u/3198595?v=3","gravatar_id":"","url":"https://api.github.com/users/cybergeek94","html_url":"https://github.com/cybergeek94","followers_url":"https://api.github.com/users/cybergeek94/followers","following_url":"https://api.github.com/users/cybergeek94/following{/other_user}","gists_url":"https://api.github.com/users/cybergeek94/gists{/gist_id}","starred_url":"https://api.github.com/users/cybergeek94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cybergeek94/subscriptions","organizations_url":"https://api.github.com/users/cybergeek94/orgs","repos_url":"https://api.github.com/users/cybergeek94/repos","events_url":"https://api.github.com/users/cybergeek94/events{/privacy}","received_events_url":"https://api.github.com/users/cybergeek94/received_events","type":"User","site_admin":false},"comments":2,"review_comments":0,"commits":22,"additions":1231,"deletions":1568,"changed_files":17}}