-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #464 from restic/rest-backend
Add REST backend
- Loading branch information
Showing
13 changed files
with
612 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
/bin | ||
/restic | ||
/.vagrant | ||
/vendor/pkg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
REST Backend | ||
============ | ||
|
||
Restic can interact with HTTP Backend that respects the following REST API. The | ||
following values are valid for `{type}`: `data`, `keys`, `locks`, `snapshots`, | ||
`index`, `config`. `{path}` is a path to the repository, so that multiple | ||
different repositories can be accessed. The default path is `/`. | ||
|
||
## HEAD {path}/config | ||
|
||
Returns "200 OK" if the repository has a configuration, | ||
an HTTP error otherwise. | ||
|
||
## GET {path}/config | ||
|
||
Returns the content of the configuration file if the repository has a configuration, | ||
an HTTP error otherwise. | ||
|
||
Response format: binary/octet-stream | ||
|
||
## POST {path}/config | ||
|
||
Returns "200 OK" if the configuration of the request body has been saved, | ||
an HTTP error otherwise. | ||
|
||
## GET {path}/{type}/ | ||
|
||
Returns a JSON array containing the names of all the blobs stored for a given type. | ||
|
||
Response format: JSON | ||
|
||
## HEAD {path}/{type}/{name} | ||
|
||
Returns "200 OK" if the blob with the given name and type is stored in the repository, | ||
"404 not found" otherwise. If the blob exists, the HTTP header `Content-Length` | ||
is set to the file size. | ||
|
||
## GET {path}/{type}/{name} | ||
|
||
Returns the content of the blob with the given name and type if it is stored in the repository, | ||
"404 not found" otherwise. | ||
|
||
If the request specifies a partial read with a Range header field, | ||
then the status code of the response is 206 instead of 200 | ||
and the response only contains the specified range. | ||
|
||
Response format: binary/octet-stream | ||
|
||
## POST {path}/{type}/{name} | ||
|
||
Saves the content of the request body as a blob with the given name and type, | ||
an HTTP error otherwise. | ||
|
||
Request format: binary/octet-stream | ||
|
||
## DELETE {path}/{type}/{name} | ||
|
||
Returns "200 OK" if the blob with the given name and type has been deleted from the repository, | ||
an HTTP error otherwise. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// DO NOT EDIT, AUTOMATICALLY GENERATED | ||
package rest_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"restic/backend/test" | ||
) | ||
|
||
var SkipMessage string | ||
|
||
func TestRestBackendCreate(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestCreate(t) | ||
} | ||
|
||
func TestRestBackendOpen(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestOpen(t) | ||
} | ||
|
||
func TestRestBackendCreateWithConfig(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestCreateWithConfig(t) | ||
} | ||
|
||
func TestRestBackendLocation(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestLocation(t) | ||
} | ||
|
||
func TestRestBackendConfig(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestConfig(t) | ||
} | ||
|
||
func TestRestBackendLoad(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestLoad(t) | ||
} | ||
|
||
func TestRestBackendSave(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestSave(t) | ||
} | ||
|
||
func TestRestBackendSaveFilenames(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestSaveFilenames(t) | ||
} | ||
|
||
func TestRestBackendBackend(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestBackend(t) | ||
} | ||
|
||
func TestRestBackendDelete(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestDelete(t) | ||
} | ||
|
||
func TestRestBackendCleanup(t *testing.T) { | ||
if SkipMessage != "" { | ||
t.Skip(SkipMessage) | ||
} | ||
test.TestCleanup(t) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package rest | ||
|
||
import ( | ||
"errors" | ||
"net/url" | ||
"strings" | ||
) | ||
|
||
// Config contains all configuration necessary to connect to a REST server. | ||
type Config struct { | ||
URL *url.URL | ||
} | ||
|
||
// ParseConfig parses the string s and extracts the REST server URL. | ||
func ParseConfig(s string) (interface{}, error) { | ||
if !strings.HasPrefix(s, "rest:") { | ||
return nil, errors.New("invalid REST backend specification") | ||
} | ||
|
||
s = s[5:] | ||
u, err := url.Parse(s) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
cfg := Config{URL: u} | ||
return cfg, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package rest | ||
|
||
import ( | ||
"net/url" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func parseURL(s string) *url.URL { | ||
u, err := url.Parse(s) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
return u | ||
} | ||
|
||
var configTests = []struct { | ||
s string | ||
cfg Config | ||
}{ | ||
{"rest:http://localhost:1234", Config{ | ||
URL: parseURL("http://localhost:1234"), | ||
}}, | ||
} | ||
|
||
func TestParseConfig(t *testing.T) { | ||
for i, test := range configTests { | ||
cfg, err := ParseConfig(test.s) | ||
if err != nil { | ||
t.Errorf("test %d:%s failed: %v", i, test.s, err) | ||
continue | ||
} | ||
|
||
if !reflect.DeepEqual(cfg, test.cfg) { | ||
t.Errorf("test %d:\ninput:\n %s\n wrong config, want:\n %v\ngot:\n %v", | ||
i, test.s, test.cfg, cfg) | ||
continue | ||
} | ||
} | ||
} |
Oops, something went wrong.