[Alpha] UniversalMinecraftApi - A HTTP/WebSocket API for your server

UniversalMinecraftApi

UniversalMinecraftAPI is a well-documented plugin for multiple platforms, currently Spigot and Sponge, that allows external scripts to access data on the server by use of HTTP and WebSocket. This could for example be used to make interactive websites, mobile apps and create a web store for in-game items.

Example v1 request

POST /api/v1/call HTTP/1.1
Host: localhost:20059
Authorization: Basic YWRtaW46Y2hhbmdlbWU=
Content-Type: application/json

{
    "expression": "players.getPlayer('Koen').getUUID()"
}

Example v1 response:

[
  {
    "result": "76eea527-c2e8-3f70-ad6c-b9e1ed7d9561",
    "success": true,
    "tag": ""
  }
]

I have also already created a v2 which is a RESTful API for your server. However, this is not documented on the website yet, so probably not very usable. However, this is what it would look like:

Example v2 request

GET /api/v2/players/Koen/uuid HTTP/1.1
Host: localhost:20059
Content-Type: application/json
Authorization: Basic YWRtaW46Y2hhbmdlbWU=

Example v2 request

{
  "result": "76eea527-c2e8-3f70-ad6c-b9e1ed7d9561"
}

Links

Feedback

I would appreciate your feedback! If you think anything is missing, please open an issue on GitHub or leave a comment in this topic!

5 Likes

It looks nice, but I have a couple of questions:

  • Why not just use a RESTful system, rather than rely on a magic string that looks like a method? I read into how your expressions work, but writing something like a Java method to send a request seems very strange, when most other modern web services now use REST. This would make it much easier for web developers to get on board.
  • In your example, it would be nice to be able to do GET <root>/players/Koen/uuid. Most web developers will be used to this already.
  • I’d be really concerned about sending passwords over HTTP and other insecure channels each time. I know it might be unavoidable to use HTTP, but sending credentials each time provides a really large attack vector. Is there the option to either:
  • Add a web server certificate to the plugin to allow HTTPS traffic?
  • Restrict access to certain IP addresses, or localhost (so a proxy server that support HTTPS can be used)?
  • Make some queries public so no authorisation needs to be done?
3 Likes
  • I hadn’t really thought about a RESTful system yet because it is largely inspired on jsonapi, but it seems like a good idea.
  • It is possible to secure the server with HTTPS (see the secure section in Configuration).
  • An IP whitelist is indeed a good idea!
  • It is possible to have some public methods. If no Authorization header is supplied, the user called default will be used and by default it has permission to execute players.getPlayer and Player.getUUID(). (also documented by the way)

Fair enough, hadn’t see the section on HTTPS, nor the default user stuff.

Thanks!

this is a big nope. Never ever use ports below 1023, unless you are developing an os, hardware drivers etc.

0 is reserved. http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml

As you can see in that code, port 0 is never actually used. When I pass 0 to ServerSocket, it tries to find an available port which is used in case the port the user has selected is not available.

REST is now also available, although I haven’t updated the documentation generator yet, so there is no documentation yet. I have also updated the permission model so that the same permissions can be used for REST and the expression language.

Edit: I also added an IP whitelist and release version 0.1

Looks very promising! Great documentation, too!

Aw yiss !

I need to try this, RIGHT NOW :grey_exclamation:

Here was my request :

By the way, did you make any update ? Are you still working on it ?

Is possible to send multiple requests at once?

It does support multiple calls at once. For example:

POST /api/v1/call HTTP/1.1
Host: localhost:20059
Content-Type: application/json
Authorization: Basic YWRtaW46Y2hhbmdlbWU=

[
	{
	    "expression": "streams.listStreams()",
	    "tag": "newtag"
	},
	{
		"expression": "server.getServer().getPort()"
	},
	{
		"expression": "namespace.doesNotExists()",
		"tag": "lasttag"
	}
]

The response would be:

[
  {
    "result": [
      "chat",
      "console"
    ],
    "success": true,
    "tag": "newtag"
  },
  {
    "result": 25565,
    "success": true,
    "tag": ""
  },
  {
    "code": 2,
    "success": false,
    "tag": "lasttag",
    "message": "Error while invoking method: Unable to find namespace namespace"
  }
]

So it even handles errors per call. If you are planning to use this, please let me know so I can update it for the latest version of Sponge.

I will use it on latest version of SpongeForge, but that’s awesome news!

Alright, I have quickly updated it to the Sponge API 5.1.0 and also released it via Ore: https://ore.spongepowered.org/koesie10/UniversalMinecraftAPI

1 Like