Workhorse handlers

Long HTTP requests are hard to handle efficiently in Rails. The requests are either memory-inefficient (file uploads) or impossible at all due to shorter timeouts (for example, Puma server has 60-second timeout). Workhorse can efficiently handle a large number of long HTTP requests. Workhorse acts as a proxy that intercepts all HTTP requests and either propagates them without changing or handles them itself by performing additional logic.

Injectors

RailsWorkhorseClientRailsWorkhorseClientRequestPropagate the request as-isRespond with a special header that contains instructions for proceeding with the requestResponse

Example: Send a Git blob

GitalyRailsWorkhorseClientGitalyRailsWorkhorseClientHTTP Request for a blobPropagate the request as-isRespond with a git-blob:{encoded_data} headerBlobService.GetBlob gRPC requestBlobService.GetBlob gRPC requestStream the data

How GitLab Rails processes the request

How Workhorse processes the header

Example: Send a file

Object StorageRailsWorkhorseClientObject StorageRailsWorkhorseClientHTTP Request for a filePropagate the request as-isRespond with a send-url:{encoded_data} headerRequest for a fileStream the dataStream the data

Pre-authorized requests

Object StorageRailsWorkhorseClientObject StorageRailsWorkhorseClientAppend `/authorize` to the original URL and call Rails for an Auth checkWorkhorse calls the original URL to create a database recordPUT /artifacts/uploadsGET /artifacts/uploads/authorizeAuthorized successfullyStream the file contentUpload the fileSuccessFinalize the requestFinalized successfullyUploaded successfully

Git over HTTP(S)

Workhorse accelerates Git over HTTP(S) by handling Git HTTP protocol requests. For example, Git push/pull may require serving large amounts of data. To avoid transferring it through GitLab Rails, Workhorse only performs authorization checks against GitLab Rails, then performs a Gitaly gRPC request directly, and streams the data from Gitaly to the Git client.

Git pull

GitalyRailsWorkhorseGit on clientGitalyRailsWorkhorseGit on clientgit clone/fetchAccess check/Log activityAccess check/Update statisticsGET /foo/bar.git/info/refs/?service=git-upload-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.InfoRefsUploadPack gRPC requestSmartHTTPService.InfoRefsUploadPack gRPC responsesend info-refs responseGET /foo/bar.git/info/refs/?service=git-upload-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.PostUploadPackWithSidechannel gRPC requestSmartHTTPService.PostUploadPackWithSidechannel gRPC responsesend response

Git push

GitalyRailsWorkhorseGit on clientGitalyRailsWorkhorseGit on clientgit pushAccess check/Log activityAccess check/Update statisticsGET /foo/bar.git/info/refs/?service=git-receive-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.InfoRefsReceivePack gRPC requestSmartHTTPService.InfoRefsReceivePack gRPC responsesend info-refs responseGET /foo/bar.git/info/refs/?service=git-receive-packGET Repositories::GitHttpController200 OK, Gitlab::Workhorse.git_http_okSmartHTTPService.PostReceivePackWithSidechannel gRPC requestSmartHTTPService.PostReceivePackWithSidechannel gRPC responsesend response