Add SHA256 and HEAD on File API
This commit is contained in:
parent
a17d0527be
commit
80f4e7575e
5 changed files with 180 additions and 11 deletions
5
changelogs/unreleased/19439-api-file-sha56-and-head.yml
Normal file
5
changelogs/unreleased/19439-api-file-sha56-and-head.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add SHA256 and HEAD on File API
|
||||
merge_request: 19439
|
||||
author: ahmet2mir
|
||||
type: added
|
|
@ -27,6 +27,7 @@ Example response:
|
|||
"size": 1476,
|
||||
"encoding": "base64",
|
||||
"content": "IyA9PSBTY2hlbWEgSW5mb3...",
|
||||
"content_sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481",
|
||||
"ref": "master",
|
||||
"blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
|
||||
"commit_id": "d5a3ff139356ce33e37e73add446f16869741b50",
|
||||
|
@ -39,6 +40,36 @@ Parameters:
|
|||
- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
|
||||
- `ref` (required) - The name of branch, tag or commit
|
||||
|
||||
NOTE: **Note:**
|
||||
`blob_id` is the blob sha, see [repositories - Get a blob from repository](repositories.md#get-a-blob-from-repository)
|
||||
|
||||
In addition to the `GET` method, you can also use `HEAD` to get just file metadata.
|
||||
|
||||
```
|
||||
HEAD /projects/:id/repository/files/:file_path
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --head --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
...
|
||||
X-Gitlab-Blob-Id: 79f7bbd25901e8334750839545a9bd021f0e4c83
|
||||
X-Gitlab-Commit-Id: d5a3ff139356ce33e37e73add446f16869741b50
|
||||
X-Gitlab-Content-Sha256: 4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481
|
||||
X-Gitlab-Encoding: base64
|
||||
X-Gitlab-File-Name: key.rb
|
||||
X-Gitlab-File-Path: app/models/key.rb
|
||||
X-Gitlab-Last-Commit-Id: 570e7b2abdd848b95f2f578043fc23bd6f6fd24d
|
||||
X-Gitlab-Ref: master
|
||||
X-Gitlab-Size: 1476
|
||||
...
|
||||
```
|
||||
|
||||
## Get raw file from repository
|
||||
|
||||
```
|
||||
|
@ -54,6 +85,9 @@ Parameters:
|
|||
- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
|
||||
- `ref` (required) - The name of branch, tag or commit
|
||||
|
||||
NOTE: **Note:**
|
||||
Like [Get file from repository](repository_files.md#get-file-from-repository) you can use `HEAD` to get just file metadata.
|
||||
|
||||
## Create new file in repository
|
||||
|
||||
```
|
||||
|
|
|
@ -5,6 +5,8 @@ module API
|
|||
# Prevents returning plain/text responses for files with .txt extension
|
||||
after_validation { content_type "application/json" }
|
||||
|
||||
helpers ::API::Helpers::HeadersHelpers
|
||||
|
||||
helpers do
|
||||
def commit_params(attrs)
|
||||
{
|
||||
|
@ -40,6 +42,20 @@ module API
|
|||
}
|
||||
end
|
||||
|
||||
def blob_data
|
||||
{
|
||||
file_name: @blob.name,
|
||||
file_path: @blob.path,
|
||||
size: @blob.size,
|
||||
encoding: "base64",
|
||||
content_sha256: Digest::SHA256.hexdigest(@blob.data),
|
||||
ref: params[:ref],
|
||||
blob_id: @blob.id,
|
||||
commit_id: @commit.id,
|
||||
last_commit_id: @repo.last_commit_id_for_path(@commit.sha, params[:file_path])
|
||||
}
|
||||
end
|
||||
|
||||
params :simple_file_params do
|
||||
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
|
||||
requires :branch, type: String, desc: 'Name of the branch to commit into. To create a new branch, also provide `start_branch`.'
|
||||
|
@ -61,6 +77,17 @@ module API
|
|||
requires :id, type: String, desc: 'The project ID'
|
||||
end
|
||||
resource :projects, requirements: FILE_ENDPOINT_REQUIREMENTS do
|
||||
desc 'Get raw file metadata from repository'
|
||||
params do
|
||||
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
|
||||
requires :ref, type: String, desc: 'The name of branch, tag or commit'
|
||||
end
|
||||
head ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
|
||||
assign_file_vars!
|
||||
|
||||
set_http_headers(blob_data)
|
||||
end
|
||||
|
||||
desc 'Get raw file contents from the repository'
|
||||
params do
|
||||
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
|
||||
|
@ -69,9 +96,22 @@ module API
|
|||
get ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
|
||||
assign_file_vars!
|
||||
|
||||
set_http_headers(blob_data)
|
||||
|
||||
send_git_blob @repo, @blob
|
||||
end
|
||||
|
||||
desc 'Get file metadata from repository'
|
||||
params do
|
||||
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
|
||||
requires :ref, type: String, desc: 'The name of branch, tag or commit'
|
||||
end
|
||||
head ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
|
||||
assign_file_vars!
|
||||
|
||||
set_http_headers(blob_data)
|
||||
end
|
||||
|
||||
desc 'Get a file from the repository'
|
||||
params do
|
||||
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
|
||||
|
@ -80,17 +120,11 @@ module API
|
|||
get ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
|
||||
assign_file_vars!
|
||||
|
||||
{
|
||||
file_name: @blob.name,
|
||||
file_path: @blob.path,
|
||||
size: @blob.size,
|
||||
encoding: "base64",
|
||||
content: Base64.strict_encode64(@blob.data),
|
||||
ref: params[:ref],
|
||||
blob_id: @blob.id,
|
||||
commit_id: @commit.id,
|
||||
last_commit_id: @repo.last_commit_id_for_path(@commit.sha, params[:file_path])
|
||||
}
|
||||
data = blob_data
|
||||
|
||||
set_http_headers(data)
|
||||
|
||||
data.merge(content: Base64.strict_encode64(@blob.data))
|
||||
end
|
||||
|
||||
desc 'Create new file in repository'
|
||||
|
|
11
lib/api/helpers/headers_helpers.rb
Normal file
11
lib/api/helpers/headers_helpers.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
module API
|
||||
module Helpers
|
||||
module HeadersHelpers
|
||||
def set_http_headers(header_data)
|
||||
header_data.each do |key, value|
|
||||
header "X-Gitlab-#{key.to_s.split('_').collect(&:capitalize).join('-')}", value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,6 +21,89 @@ describe API::Files do
|
|||
"/projects/#{project.id}/repository/files/#{file_path}"
|
||||
end
|
||||
|
||||
describe "HEAD /projects/:id/repository/files/:file_path" do
|
||||
shared_examples_for 'repository files' do
|
||||
it 'returns file attributes in headers' do
|
||||
head api(route(file_path), current_user), params
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response.headers['X-Gitlab-File-Path']).to eq(CGI.unescape(file_path))
|
||||
expect(response.headers['X-Gitlab-File-Name']).to eq('popen.rb')
|
||||
expect(response.headers['X-Gitlab-Last-Commit-Id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
|
||||
expect(response.headers['X-Gitlab-Content-Sha256']).to eq('c440cd09bae50c4632cc58638ad33c6aa375b6109d811e76a9cc3a613c1e8887')
|
||||
end
|
||||
|
||||
it 'returns file by commit sha' do
|
||||
# This file is deleted on HEAD
|
||||
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
|
||||
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
|
||||
|
||||
head api(route(file_path), current_user), params
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response.headers['X-Gitlab-File-Name']).to eq('commit.js.coffee')
|
||||
expect(response.headers['X-Gitlab-Content-Sha256']).to eq('08785f04375b47f81f46e68cc125d5ef368aa20576ddb53f91f4d83f1d04b929')
|
||||
end
|
||||
|
||||
context 'when mandatory params are not given' do
|
||||
it "responds with a 400 status" do
|
||||
head api(route("any%2Ffile"), current_user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(400)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when file_path does not exist' do
|
||||
it "responds with a 404 status" do
|
||||
params[:ref] = 'master'
|
||||
|
||||
head api(route('app%2Fmodels%2Fapplication%2Erb'), current_user), params
|
||||
|
||||
expect(response).to have_gitlab_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when file_path does not exist' do
|
||||
include_context 'disabled repository'
|
||||
|
||||
it "responds with a 403 status" do
|
||||
head api(route(file_path), current_user), params
|
||||
|
||||
expect(response).to have_gitlab_http_status(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when unauthenticated', 'and project is public' do
|
||||
it_behaves_like 'repository files' do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:current_user) { nil }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when unauthenticated', 'and project is private' do
|
||||
it "responds with a 404 status" do
|
||||
current_user = nil
|
||||
|
||||
head api(route(file_path), current_user), params
|
||||
|
||||
expect(response).to have_gitlab_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated', 'as a developer' do
|
||||
it_behaves_like 'repository files' do
|
||||
let(:current_user) { user }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated', 'as a guest' do
|
||||
it_behaves_like '403 response' do
|
||||
let(:request) { head api(route(file_path), guest), params }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/repository/files/:file_path" do
|
||||
shared_examples_for 'repository files' do
|
||||
it 'returns file attributes as json' do
|
||||
|
@ -30,6 +113,7 @@ describe API::Files do
|
|||
expect(json_response['file_path']).to eq(CGI.unescape(file_path))
|
||||
expect(json_response['file_name']).to eq('popen.rb')
|
||||
expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
|
||||
expect(json_response['content_sha256']).to eq('c440cd09bae50c4632cc58638ad33c6aa375b6109d811e76a9cc3a613c1e8887')
|
||||
expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
|
||||
end
|
||||
|
||||
|
@ -51,6 +135,7 @@ describe API::Files do
|
|||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(json_response['file_name']).to eq('commit.js.coffee')
|
||||
expect(json_response['content_sha256']).to eq('08785f04375b47f81f46e68cc125d5ef368aa20576ddb53f91f4d83f1d04b929')
|
||||
expect(Base64.decode64(json_response['content']).lines.first).to eq("class Commit\n")
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue