Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP API #895

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
166 changes: 166 additions & 0 deletions HTTPAPI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Features

* Check current status (on/off)

- Turn on/off or toggle the client
- Get server list
- Get current server
- Activate server
- Add new server
- Modify server
- Delete server
- Get current mode
- Switch mode

# Specification

**PORT:** 9528

### HTTP Status Code

- 200 - Succeed
- 400 - Fail
- 404 (For `PATCH /servers/{ID}` and `DELETE /servers/{ID}`) - `{ID}` Not found
- 404 (For `GET /current`) No server is activated

### Methods

Note: To run the sample shell commands, replace the `Id` (if any) below for your own ones.

- #### Check current status (on/off) `GET /status`

###### Sample Shell command

```shell
$ curl -X GET http://localhost:9528/status
```

###### Sample Return

```json
{"Enable": true}
```

- #### Turn on/off or toggle the client `PUT /status`

###### Sample Shell command

```shell
curl -X PUT http://localhost:9528/status -d 'Enable=false'
```

Omit the argument `Enable` to **toggle**.

- #### Get server list `GET /servers`

###### Sample Shell command

```shell
$ curl -X GET http://localhost:9528/servers
```

###### Sample Return

```json
[
{
"Id" : "93C127E0-49C9-4332-9CAD-EE6B9A3D1A8F",
"Method" : "chacha20-ietf-poly1305",
"Password" : "password",
"Plugin" : "",
"PluginOptions" : "",
"Remark" : "jp1",
"ServerHost" : "jp1-sta40.somehost.com",
"ServerPort" : 49234
},
{
"Id" : "71552DCD-B298-4591-B59A-82DA4B07AEF8",
"Method" : "chacha20-ietf-poly1305",
"Password" : "password",
"Plugin" : "",
"PluginOptions" : "",
"Remark" : "us1",
"ServerHost" : "us1-sta40.somehost.com",
"ServerPort" : 49234
},...
]
```

- #### Get current server `GET /current`

###### Sample Shell command

```shell
$ curl -X GET http://localhost:9528/current
```

###### Sample Return

```json
{
"Id" : "93C127E0-49C9-4332-9CAD-EE6B9A3D1A8F",
"Method" : "chacha20-ietf-poly1305",
"Password" : "password",
"Plugin" : "",
"PluginOptions" : "",
"Remark" : "jp1",
"ServerHost" : "jp1-sta40.somehost.com",
"ServerPort" : 49234
}
```

- #### Activate server `PUT /current`

###### Sample Shell command

```shell
$ curl -X PUT http://localhost:9528/current -d 'Id=71552DCD-B298-4591-B59A-82DA4B07AEF8'
```

- #### Add Server `POST /servers `

###### Sample Shell command

```shell
$ curl -X POST http://localhost:9528/servers -d 'ServerPort=6666&ServerHost=tw1-sta40.somehost.com&Remark=someRemark&PluginOptions=&Plugin=&Password=myPassword&Method=chacha20-ietf-poly1305'
```

- #### Modify Server `PATCH /servers/{ID} `

###### Sample Shell command

```shell
$ curl -X PATCH http://localhost:9528/servers/71552DCD-B298-4591-B59A-82DA4B07AEF8 -d 'ServerPort=6666&Remark=someRemark'
```

- #### Delete Server `DELETE /server/{ID}`

###### Sample Shell command

```shell
$ curl -X DELETE http://localhost:9528/servers/71552DCD-B298-4591-B59A-82DA4B07AEF8
```

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

###### Sample Shell command

```shell
$ curl -X GET http://localhost:9528/mode
```

###### Sample Return

```json
{"Mode": "auto"}
```

`mode`∈ {"auto", "global", "manual"}.

- #### Switch mode `PUT /mode`

###### Sample Shell command

```shell
$ curl -X PUT http://localhost:9528/status -d 'Mode=global'
```
73 changes: 19 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,28 @@
# ShadowsocksX-NG
# ShadowsocksX-NG, API Supported

Current version is 1.8.2
Current version is 1.8.2 develop.

[![Build Status](https://travis-ci.org/shadowsocks/ShadowsocksX-NG.svg?branch=develop)](https://travis-ci.org/shadowsocks/ShadowsocksX-NG)
This is a fork with minor feature added. All credits go to the **original authors**.

Next Generation of [ShadowsocksX](https://github.com/shadowsocks/shadowsocks-iOS)
## Introduction

## Why a new implementation?
[shadowsocks/**ShadowsocksX-NG**](https://github.com/shadowsocks/ShadowsocksX-NG) doesn't support Alfred control. So I copy code from its obsolete fork [yichengchen/**ShadowsocksX-R**](https://github.com/yichengchen/ShadowsocksX-R/blob/42b409beb85aee19a4852e09e7c3e4c2f73f49d3/ShadowsocksX-NG/ApiServer.swift) to euip the app with **HTTP API**, enabling Alfred Control. You may want to download the **Alfred workflow** from [yangziy/Alfred_ShadowsocksController](https://github.com/yangziy/Alfred_ShadowsocksController).

It's hard to maintain the original implementation as there is too much unused code in it.
It also embeds the `ss-local` source. It's crazy to maintain dependencies of `ss-local`.
So it's hard to update the `ss-local` version.
With the **HTTP API** you could also control the app with **curl** in **terminal**.

Now I just copied the `ss-local` from Homebrew. Run `ss-local` executable as a Launch Agent in the background.
Serve PAC JS file as a file URL. So there is only some source code related to GUI left.
Then I will rewrite the GUI code in Swift.
## Feature

## Requirements
The **HTTP API** enables users to do the following:

### Running

- macOS 10.11+

### Building

- Xcode 10.0+
- CocoaPods 1.5.3+

## Download

From [here](https://github.com/shadowsocks/ShadowsocksX-NG/releases/)

## Features

- `ss-local` from shadowsocks-libev 3.2.0
- Support SIP003 plugins. Embed `kcptun` and `simple-obfs`.
- Could update PAC by download GFW List from GitHub.
- Share your server profiles by qrcode or url.
- Import server profile urls from pasteboard.
- Import server profile by scan QRCode on screen.
- Custom rules for PAC.
- Support for [AEAD Ciphers](https://shadowsocks.org/en/spec/AEAD-Ciphers.html)
- HTTP Proxy by [privoxy](http://www.privoxy.org/)

## Difference from original ShadowsocksX

`ss-local` is run as a background service through launchd, not as an in-app process.
So after you quit the app, the `ss-local` might be still running.

Added a manual mode which won't configure the system proxy settings,
so that you could configure your apps to use the SOCKS5 proxy manually.

## Contributing

Contributions must be available on a separately named branch based on the latest version of the main branch `develop`.

ref: [GitFlow](http://nvie.com/posts/a-successful-git-branching-model/)

## License

The project is released under the terms of the GPLv3.
- Check current status (on/off)
- Turn on/off or toggle the client
- Get server list
- Add new server
- Modify server
- Delete server
- Get current server
- Select server
- Get current mode
- Switch mode

For usage, consult [HTTP API Specification](https://github.com/yangziy/ShadowsocksX-NG_WithAPI/blob/master/HTTPAPI.md) .
4 changes: 4 additions & 0 deletions ShadowsocksX-NG.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
1C82DBA81FA96C7500B32551 /* obfs-local in Resources */ = {isa = PBXBuildFile; fileRef = 1C82DBA51FA96C7400B32551 /* obfs-local */; };
1C82DBAA1FA96FB600B32551 /* install_simple_obfs.sh in Resources */ = {isa = PBXBuildFile; fileRef = 1C82DBA91FA96F0300B32551 /* install_simple_obfs.sh */; };
258E511BA910B0521B24DAB8 /* Pods_ShadowsocksX_NG.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 283ED1A8E9B711AC65670031 /* Pods_ShadowsocksX_NG.framework */; };
8EE2EDD9214F7CEC00FB4562 /* HTTPUserProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EE2EDD6214F7CEC00FB4562 /* HTTPUserProxy.swift */; };
9B07EFA71D048BBB0052D9DF /* ss-local in Resources */ = {isa = PBXBuildFile; fileRef = 9B07EFA61D048BBB0052D9DF /* ss-local */; };
9B07EFAC1D048E880052D9DF /* menu_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B07EFA81D048E880052D9DF /* menu_icon@2x.png */; };
9B07EFAD1D048E880052D9DF /* menu_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B07EFA91D048E880052D9DF /* menu_icon.png */; };
Expand Down Expand Up @@ -148,6 +149,7 @@
50D54926AA21B0D4D8DD9C4F /* Pods-ShadowsocksX-NGUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NGUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NGUITests/Pods-ShadowsocksX-NGUITests.release.xcconfig"; sourceTree = "<group>"; };
58907E7F50405104B42CB189 /* Pods-ShadowsocksX-NGUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NGUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NGUITests/Pods-ShadowsocksX-NGUITests.debug.xcconfig"; sourceTree = "<group>"; };
5B6203C1228FCD3D365814AC /* Pods-ShadowsocksX-NGTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NGTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NGTests/Pods-ShadowsocksX-NGTests.debug.xcconfig"; sourceTree = "<group>"; };
8EE2EDD6214F7CEC00FB4562 /* HTTPUserProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPUserProxy.swift; sourceTree = "<group>"; };
9B07EFA61D048BBB0052D9DF /* ss-local */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = "ss-local"; sourceTree = "<group>"; };
9B07EFA81D048E880052D9DF /* menu_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menu_icon@2x.png"; sourceTree = "<group>"; };
9B07EFA91D048E880052D9DF /* menu_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_icon.png; sourceTree = "<group>"; };
Expand Down Expand Up @@ -366,6 +368,7 @@
isa = PBXGroup;
children = (
9BB706A51D1B982300551F0E /* SWBApplication.m */,
8EE2EDD6214F7CEC00FB4562 /* HTTPUserProxy.swift */,
9BB706A61D1B982300551F0E /* SWBApplication.h */,
9B3FFF511D09DBA20019A709 /* ShadowsocksX-NG-Bridging-Header.h */,
9B3FFF151D072FDE0019A709 /* LaunchAtLoginController.h */,
Expand Down Expand Up @@ -842,6 +845,7 @@
9BB706A71D1B982300551F0E /* SWBApplication.m in Sources */,
9B3FFF1E1D0732660019A709 /* Utils.m in Sources */,
9B7297EA214D7C6B00FD24AA /* ShareServerProfilesWindowController.swift in Sources */,
8EE2EDD9214F7CEC00FB4562 /* HTTPUserProxy.swift in Sources */,
9B3FFF321D08CEE40019A709 /* SWBQRCodeWindowController.m in Sources */,
9B3FFF211D08826E0019A709 /* PACUtils.swift in Sources */,
9B3FFF141D0705810019A709 /* Notifications.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions ShadowsocksX-NG/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele

// Register global hotkey
ShortcutsController.bindShortcuts()

// Start HTTP API Server
HTTPUserProxy.shard.start()
}

func applicationWillTerminate(_ aNotification: Notification) {
Expand Down