mirror of
https://github.com/qdm12/ddns-updater.git
synced 2026-08-02 10:38:41 -04:00
Document SHOUTRRR_PARAMS: Your SHOUTRRR integration for generic webhooks only sends a string in the body when the default is application/json #243
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @HansBaumgaertner on GitHub (Jan 11, 2023).
Originally assigned to: @qdm12 on GitHub.
Hi Quentin,
First off, long time user of your container with much happiness.
Second, I have a bit of a problem that I managed to solve on my own, however for those that didn't go as far as I went to fix it, this bug report is to save them time.
I recently had a reason to use the notifications your container can generate with the SHOUTRRR integration. The idea was to grab the output from a generic webhook to trigger a Node-Red flow which would then update my custom-whitelist.yaml file with the updated dynamic IP address so I just would need restart my Crowdsec container for the changes to take affect. This proved to be a bit more difficult.
Your documentation points everyone to go to the SHOUTRRR docs for the directions to properly setup the integrations for their supported services, however it is not mentioned that most of what you have exposed in your integration is centered around Gotify (which works for most users) and a half-integrated generic webhook.
I and someone else spent many hours trying to figure out if it was Node-Red or Shoutrrr that was at fault for why we were only getting error 400 responses from the DDNS-Updater container when trying to send a generic webhook to a Node-Red endpoint. Node-Red's logs reported that there was a JSON error at position 0 with the character "L".
To narrow down the problem more, I spun up a generic webhook container on my server to get the full message headers and body for troubleshooting. The results of that test concluded that the Content Type sent was application/json, but the body of the message was a string. This meant that Node-Red was expecting application/json, but was throwing an error due to receiving a string. No problem, the default output from SHOUTRRR is application/json, so all that needs to be done is to change the content type based on the documentation that you linked to.
This is where the problem got worse. No matter if I included in the generic webhook URL extra parameters like ?contenttype=text/plain, it would ignore all of that. I tried searching endlessly on the SHOUTRRR forums thinking I had done a configuration problem. Nothing I threw at it seemed to work.
So, since I ran out of ideas, I decided to open your code and take a look to see if there was something I could find that could help me narrow down what the problem was. I am not a Golang expert and to date have written 0 lines of go code. However, I was determined to find the problem.
What I discovered was an undocumented env var in your code called SHOUTRRR_PARAMS which looked like it was the missing piece to my problem. Here is a screenshot of that bit taken from shoutrrr.go:

Once I dropped in that env var into my compose file and set it to contenttype=text/plain, everything reported properly on the webhook tester app and then worked flawlessly in Node-Red.
Moving forward, it would be good to have a look at your SHOUTRRR integration and documentation again. I only say this because of what I went through, but also since you have documented SHOUTRRR_ADDRESSES as a comma separated list of addresses to send to, but only with 1 configurable content type for the entire list. If I wanted to have included a webhook notification for Discord plus Node-Red, Discord would have failed since it expects a JSON formatted POST, but I had changed the content type to text/plain. Without changing the content type from the default, Discord would have not accepted a plain string in the body.
Please have a look at my suggestions and if you need someone to test the updates, I would be happy to for you. Thanks!
@qdm12 commented on GitHub (Jun 12, 2023):
First of all, sorry for the many hours wasted, and this is definitely a nifty horrible bug and missing documentation.
Second, sorry for the massive delay, I was moving continents, and didn't have time to maintain much my projects.
See #411 as far as I have seen, sadly, I don't think you can configure a content type per service if you cannot do it using
SHOUTRRR_PARAMS'; I even dug quite a bit in the Go shoutrrr library. So I'm thinking now to move everything to JSON, such that the default generic content type would work, what do you think?@qdm12 commented on GitHub (Jun 12, 2023):
@DennisGaida @HansBaumgaertner
Quoting from the PR adding documentation for
SHOUTRRR_PARAMSwhich links to this issue:Or should we just leave everything as is, let Shoutrrr handles its thing and keep the link from the readme
SHOUTRRR_PARAMSvariable documentation to this issue?@DennisGaida commented on GitHub (Jun 12, 2023):
My application (Node-Red https://nodered.org/) would definitely work with
application/json- this is what it expects. What doesn't work is sending raw test and saying "this is json" when it isn't - hence my issue.I believe it would be totally fine if we'd document this cleanly - we are not here to fix / improve Shoutrrr. Sending JSON for everything sounds nice to me, but maybe that doesn't work with all services? Json should be the default anyways IMHO compared to plain text, but that may just be my opinion.
@qdm12 commented on GitHub (Jun 12, 2023):
DDNS updater?@DennisGaida commented on GitHub (Jun 12, 2023):
Check the shoutrrr documentation - it unfortunately is different per service.
Node-Red really doesn't care what JSON data you throw at it. Add a title. Add a description. Add anything - you will have to deal with parsing everything anyways. All it wants is valid JSON if you say you send JSON 😉
Again: the raw message. So if I send "this a test" as content type
text/plainthis is what I receive. When I send{ "title":"DDNS updater", "message":"this is a message"}asapplication/jsonI would receive exactly that raw JSON.@qdm12 commented on GitHub (Jun 12, 2023):
I created https://github.com/containrrr/shoutrrr/issues/363 to get some clarifications. I still tend to think the default on shoutrrr should be
text/plain, and, especially important if not, we need a way to specify the content type per service.@piksel commented on GitHub (Jun 13, 2023):
Sorry if I misunderstand something, but couldn't you just use:
(for a json-encoded object, with
titleandmessage) or(for just the message as a string)
The
PARAMSare used to set the title because we didn't add thetitleas a standardized field until later in shoutrrrrs lifetime, so it's a bit of a hack unfortunately. Everything you can put inPARAMS, you could just as well put in the URL to begin with.Everything in the params will be sent to all notification services, so it is probably not a good idea to expose it to the end users, since
titleis the only thing you can safely pass to all services without them complaining about unknown keys.@qdm12 commented on GitHub (Jun 13, 2023):
@piksel thanks so much for your input over here 🎖️
Given your comment, I removed the recently added documentation about
SHOUTRRR_PARAMSin5455207852(ideally I'll remove it when doing a breaking change release).@HansBaumgaertner @DennisGaida how come you were not aware of such address options? Maybe an interesting documentation update to be done for Shoutrrr 🤔
@piksel commented on GitHub (Jun 13, 2023):
Yeah, I am really confused by this as well. There are no examples of putting those settings in the params, only for putting them in the configuration URL itself.
The params are mentioned here, but I still don't understand why that would be the first thing to try: https://containrrr.dev/shoutrrr/0.7/services/generic/#queryparam_props
To clarify, I am not trying to shame you, I am just trying to understand what went wrong to improve the documentation and/or guide future users in the same situation.
@DennisGaida commented on GitHub (Jun 15, 2023):
@qdm12 "how come you were not aware of such address options". sounds a bit offensive. We're all doing this for fun aren't we?
Just as the OP in this issue I found the
SHOUTRRR_PARAMSin the source code of this repo and I thought this was the way of doing params for Shoutrrr in DDNS Updater. Trying to use what is there/existing. I checked what params shoutrrr allows and lo and behold there was a ContentType param. I just plugged that intoSHOUTRRR_PARAMSand it works.I totally didn't check if I could use another URL or URL params to modify the request, i.e. set the content-type this way. And honestly, I still think that it looks very clean using the additional environment variable, like so (makes it easier to see the base URL and the parameters):
Knowing now (thanks @piksel!), that I can set the content-type via the URL/URL params I don't have to use
SHOUTRRR_PARAMS. Looking at the documentation of shoutrrr I believe we are good. The default for the generic endpoint isapplication/json- why not. Personally I didn't consider being able to change the behavior via the URL since I found the "hidden"SHOUTRRR_PARAMSenvironment variable and thought this is how things should done (i.e. all URL parameters belong into the params env-var and it was simply not documented).As for documentation goes: I still consider it best practice to document the available environment variables and since the default
titleof the shoutrrr message is "DDNS Updater" it should be known to users that you could change this default behavior by overriding thetitlevia the URL - or can they? I didn't try it now, but does theSHOUTRRR_ADDRESSEStake precedence over the environment parameterSHOUTRRR_PARAMSor would thetitlealways be "DDNS Updater" (maybe a user would want this changed to something else?).In short: Finding
SHOUTRRR_PARAMSin the source code I thought I found the holy grail of fixing my Node-Red endpoint that expected JSON (since that's the shoutrrr default), but received plain text from DDNS updater. And I did find a solution. Maybe not the solution 😉@qdm12 commented on GitHub (Jun 15, 2023):
Not intended to be offensive at all 😉 I guess the
how come you werecould had been aWhy were youmaybe, but I still don't see it as offensive re-reading it 😸Interesting point, if it does take precedence (I hope it does), then I would rather remove SHOUTRRR_PARAMS and let the user add it to the address for each service, to avoid confusion which is, as we've seen, a lot more costly than copy pasting a parameter for each service.
If it doesn't, perhaps a better idea would be to change SHOUTRRR_PARAMS to SHOUTRRR_TITLE to override the default title and avoid using global params 🤔
@piksel commented on GitHub (Jun 15, 2023):
Params override the corresponding values from the address, yes.
For
generic, yes, but for all of the "native" services it would probably not make much sense 🤷♀️.The main problem with exposing is that it can be very confusing that all the fields needs to be available on all of the notification services.
That seems the most useful solution to me at least. Email (
smtpservice) is the only one that "needs" a title. E-mails without a subject are generally not great.@qdm12 commented on GitHub (Jun 16, 2023):
What I coded locally:
SHOUTRRR_PARAMSis disabled and a warning redirects you to useSHOUTRRR_DEFAULT_TITLEandSHOUTRRR_ADDRESSESinstead, if you still use itDDNS updaterifSHOUTRRR_DEFAULT_TITLEis left unsettitlekey in its url parameters has the keyvaluetitle={default title}added. I do this instead of using the global shoutrrr parameters to avoid overriding a title specified for a particular address. Note this also leaves the title untouched if an address has an empty title set like?title=&otherkey=othervalue. Finally, since this modification is done after settings parsing etc., it won't show up in each shoutrrr address logged in the settings tree at program start time.Is everyone's happy with this change?
@DennisGaida commented on GitHub (Jun 16, 2023):
Sounds awesome!
@qdm12 commented on GitHub (Jun 16, 2023):
Done in
e4bb82d316TLDR: use
SHOUTRRR_DEFAULT_TITLEif you want to override the default title for every address (won't override the address specific title, if set).EDIT: Fixed
SHOUTRRR_TITLE->SHOUTRRR_DEFAULT_TITLE