Web-API [v4] - AdminPanel & RESTful web server [now with screenshots!]


#42

Getting the following when starting up the server, have tried on spongeforge-1.10.2-2221-5.2.0-BETA-2223 and spongeforge-1.10.2-2221-5.1.0-BETA-2210.

   [20:28:47] [Server thread/ERROR] [Sponge]: Could not pass FMLServerStartedEvent to Plugin{id=webapi, name=Web-API, version=2.0, description=Access Minecraft through a Web API, url=https://github.com/Valandur/Web-API, authors=[Valandur], source=/home/minecraft/mc/mods/webapi-2.0-sponge-5.1.0-SNAPSHOT.jar}
java.lang.NullPointerException
        at valandur.webapi.cache.CachedCommand.copyFrom(CachedCommand.java:28) ~[CachedCommand.class:?]
        at valandur.webapi.cache.DataCache.updateCommands(DataCache.java:264) ~[DataCache.class:?]
        at valandur.webapi.WebAPI.onServerStart(WebAPI.java:289) ~[WebAPI.class:?]
        at org.spongepowered.common.event.listener.GameStartedServerEventListener_WebAPI_onServerStart62.handle(Unknown Source) ~[?:?]
        at org.spongepowered.common.event.RegisteredListener.handle(RegisteredListener.java:95) ~[RegisteredListener.class:1.10.2-2221-5.2.0-BETA-2223]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:313) [SpongeModEventManager.class:1.10.2-2221-5.2.0-BETA-2223]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:342) [SpongeModEventManager.class:1.10.2-2221-5.2.0-BETA-2223]
        at org.spongepowered.mod.SpongeMod.onStateEvent(SpongeMod.java:234) [SpongeMod.class:1.10.2-2221-5.2.0-BETA-2223]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_111]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_111]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_111]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_111]
        at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.post(EventBus.java:275) [minecraft_server.1.10.2.jar:?]
        at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:243) [LoadController.class:?]
        at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:221) [LoadController.class:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_111]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_111]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_111]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_111]
        at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.post(EventBus.java:275) [minecraft_server.1.10.2.jar:?]
        at net.minecraftforge.fml.common.LoadController.redirect$onPost$zzb000(LoadController.java:552) [LoadController.class:?]
        at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:145) [LoadController.class:?]
        at net.minecraftforge.fml.common.Loader.serverStarted(Loader.java:868) [Loader.class:?]
        at net.minecraftforge.fml.common.FMLCommonHandler.handleServerStarted(FMLCommonHandler.java:297) [FMLCommonHandler.class:?]
        at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:433) [MinecraftServer.class:?]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]

Tried running a command using webAPI, but didn't work.


#43

What other plugins have you got on the server?
Web-API tries to cache all commands that can be run on the server when starting, and it sounds like that is failing. Maybe because a plugin has a type of command that isn't supported by the Web-API yet?
Will look into it, possible fix on Monday


#44

Nvm @tridaak I found the bug it's my bad. I will fix this by Monday.


#45

All good :slight_smile: Pretty excited for the update, will have more time then anyways to test everything out.


#46

Released version 2.0.1 on github & ore which fixes the bug. Still a prerelease though, might contain more bugs.

I realised i didnt make any command examples, so here is one:
Assuming you have a hook in the command part of the hooks.conf file that looks similar to this:

...
{
  name = "redeem"
  address = "http://localhost:25000/"
  method = POST
  headers = [{
    name = "x-webapi-key"
    value = "supersecretkey"
  }]
  params = [{
    name = player
    type = player
  }]
  ...
}
...

Now you can run the command /webapi notify redeem @p on the server, and the webserver listening on localhost:25000 (the adress specified) will receive a POST request with a json body which looks similar to this:

{
  "player": {
    "name": "Valandur",
    "uuid": "xxxx-xxxx-..."
  }
}

Note that when using the @a parameter (all) it currebtly only sends the first. I will fix this.


Side note

I also started working on some short tutorials which you can find here


#47

Getting a lot of these:

[20:41:20] [Server thread/ERROR] [Sponge]: Could not pass DestructEntityEvent$Death$Impl to Plugin{id=webapi, name=Web-API, version=2.0.1, description=Access Minecraft through a Web API, ur
l=https://github.com/Valandur/Web-API, authors=[Valandur], source=/home/minecraft/mc/mods/webapi-2.0.1-sponge-5.1.0-SNAPSHOT.jar}
java.lang.ClassCastException: com.pixelmonmod.pixelmon.entities.pixelmon.EntityPixelmon cannot be cast to org.spongepowered.api.entity.living.player.Player
        at valandur.webapi.WebAPI.onEntityDespawn(WebAPI.java:344) ~[WebAPI.class:?]
        at org.spongepowered.common.event.listener.DestructEntityEventListener_WebAPI_onEntityDespawn59.handle(Unknown Source) ~[?:?]
        at org.spongepowered.common.event.RegisteredListener.handle(RegisteredListener.java:95) ~[RegisteredListener.class:1.10.2-2221-5.1.0-BETA-2210]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:313) [SpongeModEventManager.class:1.10.2-2221-5.1.0-BETA-2210]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:297) [SpongeModEventManager.class:1.10.2-2221-5.1.0-BETA-2210]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:338) [SpongeModEventManager.class:1.10.2-2221-5.1.0-BETA-2210]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:326) [SpongeModEventManager.class:1.10.2-2221-5.1.0-BETA-2210]
        at org.spongepowered.common.SpongeImpl.postEvent(SpongeImpl.java:143) [SpongeImpl.class:1.10.2-2221-5.1.0-BETA-2210]
        at org.spongepowered.common.event.SpongeCommonEventFactory.callDestructEntityEventDeath(SpongeCommonEventFactory.java:497) [SpongeCommonEventFactory.class:1.10.2-2221-5.1.0-BETA-221
0]
        at net.minecraft.entity.EntityLivingBase.func_70645_a(EntityLivingBase.java:3080) [sf.class:?]
        at net.minecraft.entity.passive.EntityTameable.func_70645_a(SourceFile:204) [sq.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity3HasStats.func_70645_a(Entity3HasStats.java:316) [Entity3HasStats.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity8HoldsItems.func_70645_a(Entity8HoldsItems.java:213) [Entity8HoldsItems.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.EntityPixelmon.func_70645_a(EntityPixelmon.java:144) [EntityPixelmon.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity6CanBattle.func_70097_a(Entity6CanBattle.java:255) [Entity6CanBattle.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity10CanBreed.func_70097_a(Entity10CanBreed.java:1159) [Entity10CanBreed.class:?]
        at net.minecraft.entity.EntityLivingBase.func_70030_z(EntityLivingBase.java:273) [sf.class:?]
        at net.minecraft.entity.EntityLiving.func_70030_z(EntityLiving.java:208) [sg.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity7HasAI.func_70030_z(Entity7HasAI.java:110) [Entity7HasAI.class:?]
        at net.minecraft.entity.Entity.func_70071_h_(Entity.java:359) [rw.class:?]
        at net.minecraft.entity.EntityLivingBase.func_70071_h_(EntityLivingBase.java:1932) [sf.class:?]
        at net.minecraft.entity.EntityLiving.func_70071_h_(EntityLiving.java:295) [sg.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity1Base.func_70071_h_(Entity1Base.java:339) [Entity1Base.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity2HasModel.func_70071_h_(Entity2HasModel.java:255) [Entity2HasModel.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity3HasStats.func_70071_h_(Entity3HasStats.java:536) [Entity3HasStats.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity4Textures.func_70071_h_(Entity4Textures.java:413) [Entity4Textures.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity5Rideable.func_70071_h_(Entity5Rideable.java:409) [Entity5Rideable.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity8HoldsItems.func_70071_h_(Entity8HoldsItems.java:75) [Entity8HoldsItems.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.Entity10CanBreed.func_70071_h_(Entity10CanBreed.java:109) [Entity10CanBreed.class:?]
        at com.pixelmonmod.pixelmon.entities.pixelmon.EntityPixelmon.func_70071_h_(EntityPixelmon.java:328) [EntityPixelmon.class:?]
        at org.spongepowered.common.event.tracking.TrackingUtil.tickEntity(TrackingUtil.java:156) [TrackingUtil.class:1.10.2-2221-5.1.0-BETA-2210]
        at net.minecraft.world.WorldServer.redirect$onCallEntityUpdate$zjn000(WorldServer.java:2810) [ls.class:?]
        at net.minecraft.world.World.func_72866_a(World.java:4071) [aid.class:?]
        at net.minecraft.world.WorldServer.func_72866_a(WorldServer.java:839) [ls.class:?]
        at net.minecraft.world.World.func_72870_g(World.java:1934) [aid.class:?]
        at net.minecraft.world.World.func_72939_s(World.java:5954) [aid.class:?]
        at net.minecraft.world.WorldServer.func_72939_s(WorldServer.java:2153) [ls.class:?]
        at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:709) [MinecraftServer.class:?]
        at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:387) [ld.class:?]
        at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:613) [MinecraftServer.class:?]
        at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:471) [MinecraftServer.class:?]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]

Also, how do I send POST variables over? Have this:

command=[
    {
        # This is the address of the endpoint. It may contain parameters that are replaced when being called.
        # Parameters have to be placed in curly braces, { and }, and will be a simple string (uuid of object
        # where applicable)
        address="http://domain.com/command.php"
        # Set to true or omit to enable the endpoint.
        enabled=true
        # This is a list of additional headers that is sent to the server. You can use this to e.g. specify a secret
        # key which ensures that the server knows the requests are coming from the Web-API. You may also use variables
        # here (same format as in "address"). Please note the headers "User-Agent", "Content-Type" and "Content-Length"
        # will always be overridden by the WebAPI.
        headers=[
            {
                name=X-WEBAPI-KEY
                value=MY-SUPER-SECRET-KEY
            },
            {
                name=X-TEST-HEADER
                value="{player}"
            }
        ]
        # This is the http method that is used (GET, PUT, POST or DELETE)
        method=POST
        # This is the name of the endpoint, which is used to call it via the webapi command.
        name=test
        # Here you have to specify what parameters are used in the address, headers and body.
        # Parameters in the address and headers have to be used explicitly, the body automatically contains all the
        # parameters that are listed here. The parameters are expected to show up in this order when calling the command
        params=[
            {
                name=player
                type=player
            }
        ]
    }
]

But the POST array was empty


#48

I released another version that should fix most issues still around. Version 2.0.2 is on Ore and GitHub.

Please note that the hooks.conf and cache.conf file structures have changed

@tridaak concerning the POST array: I added a new property to the hooks in the config. You can now set dataType = FORM on the hook and the data will be sent as form-urlencoded instead of json (The data itself is still json). You would then access it on php with $data = json_decode($_POST["body"]).


#49

Hmm, so some time has passed and have gotten to tinker a bit more with it, and have some concerns and suggestions:
-Was wondering if you could add command nodes to the web-api, so that players to be able to execute certain commands. Ie, webapi.notify.test for the command /webapi notify test
--Along with this, it would be nice if aliases could be assigned to it (although not a big issue, there is the aliases plugin)
--Reason something like this would be useful is for custom commands.

-Using the web-hook for commands (sends data to the server whenever someone runs a command, the source isn't identifying the player properly:
Sample output for when I run /help: {"timestamp":1490319422,"command":"help","args":[""],"source":(raw value '[RawValue of type java.lang.String]'),"result":{}}

-When the server closes, it does not fire the player_leave event, if using player_join and player_leave to calculate the amount of time the person has been playing on the server, it could lead to a problem.

Aside from that, really enjoying the changes, thanks for adding the waitTime and waitLines variables when executing commands :slight_smile:


#50

@tridaak Thanks for testing the plugin :slight_smile:

  • I am assuming with "command nodes" you mean permissions? These are already provided (I forgot to document them). The permission name is "webapi.command.notify.[name]" where name is the name of the command.
  • I'm still not sure about the aliases, it feels like it's not part of the scope of the project, but I'll think about.

  • I fixed the json output of the players, that will be in the next update.

  • I'm not sure if the server closing should be part of the sponge functionality, but I'll look into it

#51

I released version 2.1.0 on Ore and Github with the following changes:

  • Add ALL, PLAYER_KICK and PLAYER_BAN hooks
  • Add hook aliases (there you go @tridaak :wink:)
  • Add examples for swagger docs
  • Add class name and parent class name to /class endpoint

I did not make the server closing call PLAYER_LEAVE hooks, however there is a SERVER_STOP hook which can be subscribed to. (Sponge itself doesn't fire PlayerLeave events when the server is closing, so it didn't feel right to do that. Maybe I'll add this later)


#52

Nice :slight_smile: Also, any chance you could add optional parameters for the notify commands?


#53

Finally got the chance to update webapi, getting the following:

[03:02:47] [Server thread/INFO] [webapi]: Starting Web Server...
[03:02:47] [Server thread/INFO] [webapi]: jetty-9.4.z-SNAPSHOT
[03:02:47] [Server thread/INFO] [webapi]: Started o.e.j.s.h.ContextHandler@6342efb1{/,null,AVAILABLE}
[03:02:47] [Server thread/INFO] [webapi]: Started o.e.j.s.h.ContextHandler@13708ff3{/docs,null,AVAILABLE}
[03:02:47] [Server thread/INFO] [webapi]: Started o.e.j.s.ServletContextHandler@28878ab7{/api,null,AVAILABLE}
[03:02:47] [Server thread/INFO] [webapi]: Started ServerConnector@d6a4865{HTTP/1.1,[http/1.1]}{localhost:8080}
[03:02:47] [Server thread/INFO] [webapi]: Started @53385ms
[03:02:47] [Server thread/INFO] [webapi]: Web server running on http://localhost:8080/
[03:02:47] [Server thread/ERROR] [Sponge]: Could not pass FMLServerStartedEvent to Plugin{id=webapi, name=Web-API, version=2.1.0-S5.1, description=Access Minecraft through a Web API, url=ht
tps://github.com/Valandur/Web-API, authors=[Valandur], source=/home/minecraft/mc/mods/webapi-2.1.0-S5.1.jar}
java.lang.AbstractMethodError: Method net/minecraftforge/fml/common/event/FMLServerStartedEvent.getCause()Lorg/spongepowered/api/event/cause/Cause; is abstract
        at net.minecraftforge.fml.common.event.FMLServerStartedEvent.getCause(FMLServerStartedEvent.java) ~[FMLServerStartedEvent.class:?]
        at valandur.webapi.WebAPI.onServerStart(WebAPI.java:287) ~[WebAPI.class:?]
        at org.spongepowered.common.event.listener.GameStartedServerEventListener_WebAPI_onServerStart74.handle(Unknown Source) ~[?:?]
        at org.spongepowered.common.event.RegisteredListener.handle(RegisteredListener.java:95) ~[RegisteredListener.class:1.10.2-2254-5.2.0-BETA-2272]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:313) [SpongeModEventManager.class:1.10.2-2254-5.2.0-BETA-2272]
        at org.spongepowered.mod.event.SpongeModEventManager.post(SpongeModEventManager.java:342) [SpongeModEventManager.class:1.10.2-2254-5.2.0-BETA-2272]
        at org.spongepowered.mod.SpongeMod.onStateEvent(SpongeMod.java:234) [SpongeMod.class:1.10.2-2254-5.2.0-BETA-2272]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_111]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_111]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_111]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_111]
        at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.post(EventBus.java:275) [minecraft_server.1.10.2.jar:?]
        at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:243) [LoadController.class:?]
        at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:221) [LoadController.class:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_111]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_111]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_111]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_111]
        at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) [minecraft_server.1.10.2.jar:?]
        at com.google.common.eventbus.EventBus.post(EventBus.java:275) [minecraft_server.1.10.2.jar:?]
        at net.minecraftforge.fml.common.LoadController.redirect$onPost$zzb000(LoadController.java:552) [LoadController.class:?]
        at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:145) [LoadController.class:?]
        at net.minecraftforge.fml.common.Loader.serverStarted(Loader.java:868) [Loader.class:?]
        at net.minecraftforge.fml.common.FMLCommonHandler.handleServerStarted(FMLCommonHandler.java:297) [FMLCommonHandler.class:?]
        at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:433) [MinecraftServer.class:?]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]

#54

Same here, I had to go back to Sponge 5.1 to remove this problem.


#55

Hey everyone

I released a first version of v3, although I marked it as a pre-release because it might still have some issues, it should be mostly stable.

Quite a few response objects from /entity, /tile-entity, /player and /world have changed. Please make sure your code still works with the new endpoints when updating.

I have implemented the following changes:

  • Add /block endpoint to query & set blocks in the world
  • Rework endpoints to provide more consistent and better structured data
  • Add fine grained permission nodes for commands run via /cmd endpoint
  • Add 100% more error messages for endpoints

The releases are for SpongeAPI 5.2 and 6.0. 5.2 should work for 5.1 aswell.

Cheers
Valandur


Web-API - Provides an admin panel and API for your Minecraft server
#56

I will reply in this topic.

Quick release, thank you for everything :smiley:

Could you explain them ? I would like to send a post when a player logs in. Is it possible with Web-API or should I make a small plugin to do so ?


#57

That is exactly what hooks are meant for. If you check in the webapi/hooks.conf config file you will find some description there. I will try and explain it real quick.

The hooks listed in events are called when certain minecraft events happen. So for example all the hooks listed in events.player_join are called when a player joins.

A hook is basically just another endpoint (URL) which the Web-API contacts. A simple example could look like this:

events {
    player_join=[
        {
            address="http://localhost:25000"
            method=POST
            #dataType=FORM   # Add this if you're using PHP since it makes it easier to read the data
        }
    ]
}

This would send a POST request to http://localhost:25000 whenever a player joins. The request would contain a json body containing information about the player that joined.

I hope that clears things up, and I will try to add more tutorials as soon as I can :smile:


#58

This is fantastic, I didn't see hooks.conf and it's crystal clear :smiley:

Can I add headers as well ?

    headers=[
        {
            name=X-WEBAPI-KEY
            value=MY-SUPER-SECRET-KEY
        },
        {
            name=X-SOURCE-HEADER
            value="{source}"
        }
    ]

This is so perfect, huge thanks !


#59

You can add constant headers (such as the X-WEBAPI-KEY). Parameters in headers, such as {source} don't work in events (the data should already be included in the request body), they only work with the command hooks.


#60

I have released a bug fix which takes care of problems with config files. Please update to version 3.0.1 if you are using 3.0.0


#61

And v3.0.2 should fix errors when starting the server related to a Sponge bug