Skip to content

Commit 17fa8d0

Browse files
committed
Rewrite server-relevant API. Update document.
1 parent 11e05fc commit 17fa8d0

File tree

2 files changed

+143
-39
lines changed

2 files changed

+143
-39
lines changed

HTTPAPI.md

Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
* Check current status (on/off)
44

55
- Toggle the client
6-
76
- Get server list
8-
9-
- Switch server
10-
7+
- Get current server
8+
- Select server
9+
- Add new server
10+
- Delete server
1111
- Get current mode
12-
1312
- Switch mode
1413

1514
# Specification
@@ -26,60 +25,118 @@ URL: http://localhost:9528/
2625
}
2726
```
2827

29-
- #### Toggle the client `POST /toggle`
28+
- #### Toggle the client `POST /status`
3029

3130
###### Sample Return
3231

3332
```
3433
{
3534
"status": 1
36-
// 1 for toggle succeed, 0 for fail
3735
}
3836
```
3937

40-
- #### Get server list `GET /servers`
38+
`1` for success, `0` for failure.
39+
40+
- #### Get server list `GET /server/list`
4141

4242
###### Sample Return
4343

4444
```
4545
[
46-
{
47-
"active": 1,
48-
"id": "93C547E0-49C9-1234-9CAD-EE8D5C4A1A8F",
49-
"remark": "us1",
50-
// remark: as in Server Preferences Panel of the app.
51-
},
52-
{
53-
"active" : 0,
54-
"id" : "71552DCD-B298-495E-904E-82DA4B07AEF8",
55-
"remark" : "hk2"
56-
},
57-
{
58-
"active" : 0,
59-
"id" : "E8879F3D-95AE-4714-BC04-9B271C2BC52D",
60-
"remark" : "jp1"
61-
},...
46+
{
47+
"Id" : "93C127E0-49C9-4332-9CAD-EE6B9A3D1A8F",
48+
"Method" : "chacha20-ietf-poly1305",
49+
"Password" : "password",
50+
"Plugin" : "",
51+
"PluginOptions" : "",
52+
"Remark" : "jp1",
53+
"ServerHost" : "jp1-sta40.somehost.com",
54+
"ServerPort" : 49234
55+
},
56+
{
57+
"Id" : "71552DCD-B298-4591-B59A-82DA4B07AEF8",
58+
"Method" : "chacha20-ietf-poly1305",
59+
"Password" : "password",
60+
"Plugin" : "",
61+
"PluginOptions" : "",
62+
"Remark" : "us1",
63+
"ServerHost" : "us1-sta40.somehost.com",
64+
"ServerPort" : 49234
65+
},...
6266
]
6367
```
6468

65-
- #### Switch server `POST /servers`
69+
- #### Get current server `GET /server/current`
70+
71+
###### Sample Return
72+
73+
```
74+
{
75+
"Id" : "93C127E0-49C9-4332-9CAD-EE6B9A3D1A8F"
76+
}
77+
```
78+
79+
- #### Select server `POST /server/current`
6680

6781
###### Argument
6882

69-
| Name | Description | Sample |
70-
| ---- | ----------------------------- | -------------------------------------- |
71-
| id | As returned in `GET /servers` | "E8879F3D-95AE-4714-BC04-9B271C2BC52D" |
83+
| Name | Description | Sample |
84+
| ---- | --------------------------------- | -------------------------------------- |
85+
| Id | As returned in `GET /server/list` | "71552DCD-B298-4591-B59A-82DA4B07AEF8" |
7286

7387
###### Sample Return
7488

7589
```
7690
{
7791
"status": 1
78-
// 1 for succeed, 0 for fail
7992
}
8093
```
8194

82-
If the `id` is invalid or fail to match any `id` in config, "status" = 0.
95+
If the `Id` is invalid or fail to match any id in config, `"status": 0`.
96+
97+
- #### Add Server `POST /server `
98+
99+
###### Argument
100+
101+
| Name | Sample |
102+
| ------------- | ---------------------- |
103+
| ServerPort | 49234 |
104+
| ServerHost | jp1-sta40.somehost.com |
105+
| Remark | jp1 |
106+
| PluginOptions | |
107+
| Plugin | |
108+
| Password | Password |
109+
| Method | chacha20-ietf-poly1305 |
110+
111+
For meaning of the arguments, refer to `GET /server/list` and the Server Perferences Panel of the app.
112+
113+
###### Sample Return
114+
115+
```
116+
{
117+
"status": 1
118+
}
119+
```
120+
121+
- #### Delete Server `DELETE /server`
122+
123+
###### Argument
124+
125+
| Name | Description | Sample |
126+
| ---- | --------------------------------- | -------------------------------------- |
127+
| Id | As returned in `GET /server/list` | "71552DCD-B298-4591-B59A-82DA4B07AEF8" |
128+
129+
###### Sample Return
130+
131+
```
132+
{
133+
"status": 1
134+
}
135+
```
136+
137+
If `Id` == id of current server, operation will no effect, `"status":0`.
138+
139+
If `Id` not match, `"status":0`.
83140

84141
- #### Get current mode `GET /mode`
85142

@@ -95,6 +152,12 @@ If the `id` is invalid or fail to match any `id` in config, "status" = 0.
95152

96153
- #### Switch mode `POST /mode`
97154

155+
###### Argument
156+
157+
| Name | Description | Sample |
158+
| ---- | -------------------------- | -------- |
159+
| mode | As returned in `GET /mode` | "global" |
160+
98161
###### Sample Return
99162

100163
```
@@ -104,4 +167,7 @@ If the `id` is invalid or fail to match any `id` in config, "status" = 0.
104167
}
105168
```
106169

107-
If the `mode`∉ {"auto", "global", "manual"}, "status" = 0.
170+
---
171+
172+
All json names are case sensitive. Be careful.
173+

ShadowsocksX-NG/HTTPUserProxy.swift

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,36 +35,74 @@ class HTTPUserProxy{
3535
return GCDWebServerDataResponse(jsonObject: ["enable":isOn], contentType: "json")
3636
})
3737

38-
apiserver.addHandler(forMethod: "POST", path: "/toggle", request: GCDWebServerRequest.self, processBlock: {request in
38+
apiserver.addHandler(forMethod: "POST", path: "/status", request: GCDWebServerURLEncodedFormRequest.self, processBlock: {request in
3939
self.appdeleget.doToggleRunning(showToast: false)
4040
return GCDWebServerDataResponse(jsonObject: ["status":1], contentType: "json")
4141
})
4242

43-
apiserver.addHandler(forMethod: "GET", path: "/servers", request: GCDWebServerRequest.self, processBlock: {request in
43+
apiserver.addHandler(forMethod: "GET", path: "/server/list", request: GCDWebServerRequest.self, processBlock: {request in
4444

4545
var data = [[String:Any]]()
4646

4747
for each in self.SerMgr.profiles{
48-
data.append(["id":each.uuid,"remark":each.remark,
49-
"active":self.SerMgr.activeProfileId == each.uuid ? 1 : 0])
48+
data.append(each.toDictionary())
5049
}
5150

5251
return GCDWebServerDataResponse(jsonObject: data, contentType: "json")
5352
})
5453

55-
apiserver.addHandler(forMethod: "POST", path: "/servers", request: GCDWebServerURLEncodedFormRequest.self, processBlock: {request in
54+
apiserver.addHandler(forMethod: "GET", path: "/server/current", request: GCDWebServerRequest.self, processBlock: {request in
5655

57-
let uuid = ((request as! GCDWebServerURLEncodedFormRequest).arguments["id"])as? String
56+
return GCDWebServerDataResponse(jsonObject: ["Id":self.SerMgr.activeProfileId], contentType: "json")
57+
})
58+
59+
apiserver.addHandler(forMethod: "POST", path: "/server/current", request: GCDWebServerURLEncodedFormRequest.self, processBlock: {request in
60+
61+
let uuid = ((request as! GCDWebServerURLEncodedFormRequest).arguments["Id"])as? String
5862
for each in self.SerMgr.profiles{
5963
if (each.uuid == uuid) {
6064
self.appdeleget.changeServer(uuid: uuid!)
6165
return GCDWebServerDataResponse(jsonObject: ["status":1], contentType: "json")
62-
66+
6367
}
6468
}
6569
return GCDWebServerDataResponse(jsonObject: ["status":0], contentType: "json")
6670
})
6771

72+
apiserver.addHandler(forMethod: "POST", path: "/server", request: GCDWebServerURLEncodedFormRequest.self, processBlock: {request in
73+
74+
var form = ((request as! GCDWebServerURLEncodedFormRequest).arguments) as! [String: Any]
75+
form["ServerPort"] = Double(form["ServerPort"] as! String)
76+
77+
self.SerMgr.profiles.append(ServerProfile.fromDictionary(form))
78+
self.SerMgr.save()
79+
self.appdeleget.updateServersMenu()
80+
81+
return GCDWebServerDataResponse(jsonObject: ["status":1], contentType: "json")
82+
})
83+
84+
apiserver.addHandler(forMethod: "DELETE", path: "/server", request: GCDWebServerRequest.self
85+
, processBlock: {request in
86+
87+
let uuid = (request.query?["Id"])as! String
88+
89+
if (uuid == self.SerMgr.activeProfileId) {
90+
return GCDWebServerDataResponse(jsonObject: ["status":0], contentType: "json")
91+
}
92+
93+
for i in 0..<self.SerMgr.profiles.count{
94+
if (self.SerMgr.profiles[i].uuid == uuid) {
95+
self.SerMgr.profiles.remove(at: i)
96+
97+
self.SerMgr.save()
98+
self.appdeleget.updateServersMenu()
99+
100+
return GCDWebServerDataResponse(jsonObject: ["status":1], contentType: "json")
101+
}
102+
}
103+
104+
return GCDWebServerDataResponse(jsonObject: ["status":0], contentType: "json")
105+
})
68106

69107
apiserver.addHandler(forMethod: "GET", path: "/mode", request: GCDWebServerRequest.self, processBlock: {request in
70108
if let current = self.defaults.string(forKey: "ShadowsocksRunningMode"){
@@ -79,7 +117,7 @@ class HTTPUserProxy{
79117
if (arg != "auto" && arg != "global" && arg != "manual") {
80118
return GCDWebServerDataResponse(jsonObject: ["status":0], contentType: "json")
81119
}
82-
120+
83121
self.appdeleget.changeMode(mode: arg!)
84122

85123
return GCDWebServerDataResponse(jsonObject: ["status":1], contentType: "json")

0 commit comments

Comments
 (0)