Comments (17)
@YouveGotMeowxy This line is the perp:
apprise-api/apprise_api/etc/nginx.conf
Line 52 in fea552f
Comment it out (or delete it) and then mount that file in your docker compose and restart the apprise container:
i.e.
- '/opt/docker/configs/apprise/nginx.conf:/opt/apprise/webapp/etc/nginx.conf:ro'
from apprise-api.
As a final update, i pushed another Apprise release and rebuilt the Apprise API against it. So :latest
will also have you covered now
from apprise-api.
Perfect, I'm going to close this ticket!🚀
from apprise-api.
I'm not going to be too much help here as i've never used swag. But your upstream proto should be http
not https
.
from apprise-api.
@caronc Thanks. So I should set it to http, and then try to sort out the Contradictory scheme headers
error, rather than https and try to sort out the 500 error?
from apprise-api.
server {
listen 80;
server_name apprise.*;
client_max_body_size 0;
location / {
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
proxy_pass http://your.server.running.apprise:8000;
}
}
Get it workign first with http
, then start adding more configuration to NginX to secure the hosting.
from apprise-api.
Hi @caronc
That looks almost identical to what I posted with the exceptions of you're listening on 80, and I'm listening on 443, and I have the SSL config included.
Are you using the SWAG container? If not, can you give it a quick try, it's super simple to setup.
from apprise-api.
@YouveGotMeowxy i feel a bit stupid now. I didn't realize the whole point was the SSL itself 🤦♂️ .
I guess I was thinking that when dealing with a new nginx instance, just star basic and rule out the SSL completely. Just create the proxy and nothing more. SSL adds a lot of overhead and lots more reasons and things to troubleshoot IF setting up for the first time.
Your question is really loaded.... There are lots of things to consider here. First of all the subdomain
server_name apprise.*;
Unless you have DNS server, you'll need to edit your hosts file and make sure you create an entry like:
# Don't touch the localhost entry but add to it to support the subdomain
# (only required if you don't have DNS)
127.0.0.1 localhost apprise.localhost
Secondly how are you setting up this Nginx Reverse Proxy; it looks like they instruct you to go here
Apprise could be maybe the same as Bazarr (well not really at all). but the Nginx configuration on the link shared above is closed). Here is the direct link to their example.
You would perhaps need to just flip the ports around a bit:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name apprise.*;
include /config/nginx/ssl.conf;
client_max_body_size 0;
# enable for ldap auth, fill in ldap details in ldap.conf
#include /config/nginx/ldap.conf;
# enable for Authelia
#include /config/nginx/authelia-server.conf;
location / {
# enable the next two lines for http auth
#auth_basic "Restricted";
#auth_basic_user_file /config/nginx/.htpasswd;
# enable for Authelia
#include /config/nginx/authelia-location.conf;
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_app apprise;
set $upstream_port 8000;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
The part that throws me off is the last entry
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
SWAG assumes you have a container set up running as apprise
. Unless you do, this won't work.
When you do your docker --create
.
Make sure you create a network they can share... so each container you deploy (both the swag and apprise one) add something like --net apprise-swag
then you'll need to make sure you create the Apprise container with --name apprise
so that your reference in the swag initialization connects.
The other thing you can do is set up a docker-compose.yml
file perhaps and have both containers launch together (i belive docker-compose throws them both in the same network automatically so they can reference one another).
Falling back to the line that throws me off:
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
This translates (as you know) to:
proxy_pass http:/apprise:8000
So make sure you have a container called apprise
in your shared --net
or it can't link.
At least this is where i think things might be going wrong.
from apprise-api.
i feel a bit stupid now. I didn't realize the whole point was the SSL itself 🤦♂️ .
No worries, lol.
I really appreciate you taking this time out to investigate. :)
I've been using SWAG for probably 2-3 years now, and have something like 80 containers running RP'd through it, so I've got all the basics down (container names, networks, DNS (I use CF). etc.); if you compare the example in my OP with the swag RP you pasted from, the Bazarr RP, they're identical (with the exception of container name and port, and comments removed). :)
SWAG makes it easy to just add new containers by giving you the samples, then you normally just need to change the container name and port in the RP, and restart SWAG, and about 90% of the time works right out of the box. That's one of the great things about it. For apprise, I just grabbed this: https://github.com/linuxserver/reverse-proxy-confs/blob/master/_template.subdomain.conf.sample
added "apprise" for the container name (which matches the container name I created), added port 8000, and then have been stuck trying to get either http or https working at line 39.
It seems like it should be working, but I get the errors originally mentioned in the OP. :/
from apprise-api.
To be complete, here's my current non-working apprise RP, named apprise.subdomain.conf
:
## Version 2022/04/07
# make sure that your dns has a cname set for apprise and that your apprise container is not using a base url
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name apprise.*;
include /config/nginx/ssl.conf;
client_max_body_size 0;
# enable for ldap auth, fill in ldap details in ldap.conf
#include /config/nginx/ldap.conf;
# enable for Authelia
#include /config/nginx/authelia-server.conf;
location / {
# enable the next two lines for http auth
#auth_basic "Restricted";
#auth_basic_user_file /config/nginx/.htpasswd;
# enable the next two lines for ldap auth
#auth_request /auth;
#error_page 401 =200 /ldaplogin;
# enable for Authelia
#include /config/nginx/authelia-location.conf;
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_app apprise;
set $upstream_port 8000;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
# REMOVE THIS LINE BEFORE SUBMITTING: Some proxies require one or more additional location blocks for things like API or RPC endpoints.
# REMOVE THIS LINE BEFORE SUBMITTING: If the proxy you are making a sample for does not require an additional location block please remove the commented out section below.
# location ~ (/apprise)?/api {
# include /config/nginx/proxy.conf;
# include /config/nginx/resolver.conf;
# set $upstream_app apprise;
# set $upstream_port <port_number>;
# set $upstream_proto <http or https>;
# proxy_pass $upstream_proto://$upstream_app:$upstream_port;
#
# # REMOVE THIS LINE BEFORE SUBMITTING: Additional proxy settings such as headers go below this line, leave the blank line above.
# }
}
Then when going to: https://apprise.redacted.com
using http
for the set $upstream_proto http;
line, I get:
and changing the http
tp https
(normally http
is the one to use for most containers), gives this:
The apprise container log shows this (note that I was testing with both a browser, and curl, and both http and https during this):
today at 4:43:27 PM2022-06-01 16:43:27,098 INFO Set uid to user 33 succeeded
today at 4:43:27 PM2022-06-01 16:43:27,102 INFO supervisord started with pid 1
today at 4:43:28 PM2022-06-01 16:43:28,106 INFO spawned: 'gunicorn' with pid 7
today at 4:43:28 PM2022-06-01 16:43:28,110 INFO spawned: 'nginx' with pid 8
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [7] [INFO] Starting gunicorn 20.1.0
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [7] [INFO] Listening at: http://0.0.0.0:8080 (7)
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [7] [INFO] Using worker: sync
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [22] [INFO] Booting worker with pid: 22
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [23] [INFO] Booting worker with pid: 23
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [24] [INFO] Booting worker with pid: 24
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [25] [INFO] Booting worker with pid: 25
today at 4:43:28 PM[2022-06-01 16:43:28 -0500] [26] [INFO] Booting worker with pid: 26
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [27] [INFO] Booting worker with pid: 27
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [28] [INFO] Booting worker with pid: 28
today at 4:43:29 PM2022-06-01 16:43:29,120 INFO success: gunicorn entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
today at 4:43:29 PM2022-06-01 16:43:29,120 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [29] [INFO] Booting worker with pid: 29
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [30] [INFO] Booting worker with pid: 30
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [31] [INFO] Booting worker with pid: 31
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [32] [INFO] Booting worker with pid: 32
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [33] [INFO] Booting worker with pid: 33
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [34] [INFO] Booting worker with pid: 34
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [35] [INFO] Booting worker with pid: 35
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [36] [INFO] Booting worker with pid: 36
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [37] [INFO] Booting worker with pid: 37
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [38] [INFO] Booting worker with pid: 38
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [39] [INFO] Booting worker with pid: 39
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [40] [INFO] Booting worker with pid: 40
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [41] [INFO] Booting worker with pid: 41
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [42] [INFO] Booting worker with pid: 42
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [43] [INFO] Booting worker with pid: 43
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [44] [INFO] Booting worker with pid: 44
today at 4:43:29 PM[2022-06-01 16:43:29 -0500] [45] [INFO] Booting worker with pid: 45
today at 4:43:30 PM[2022-06-01 16:43:30 -0500] [46] [INFO] Booting worker with pid: 46
today at 4:43:30 PM[2022-06-01 16:43:30 -0500] [46] [INFO] Booting worker with pid: 46
today at 4:43:30 PM[2022-06-01 16:43:30 -0500] [46] [INFO] Booting worker with pid: 46
today at 4:54:01 PM10.0.2.5 - - [01/Jun/2022:16:54:01 -0500] "GET / HTTP/1.1" 400 149 "-" "curl/7.81.0"
today at 4:55:14 PM10.0.2.52 - - [01/Jun/2022:16:55:14 -0500] "GET /?error=502 HTTP/1.1" 400 149 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36"
today at 4:55:14 PM10.0.2.5 - - [01/Jun/2022:16:55:14 -0500] "GET /favicon.ico HTTP/1.1" 400 149 "https://apprise.redacted.com/?error=502" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36"
today at 4:56:00 PM10.0.2.52 - - [01/Jun/2022:16:56:00 -0500] "GET / HTTP/1.1" 400 149 "-" "curl/7.81.0"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *9 client sent invalid method while reading client request line, client: 10.0.2.52, server: , request: "���������Szvd��<켳~�K�4��K����@[_>���138�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.52 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\xC7Szvd\xB2\xE7<\xEC\xBC\xB3~\x04K\xEE4\x98\x14K\x06\x0B\x9D\xA8@[_>\xE3\xF2\xC613\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *10 client sent invalid method while reading client request line, client: 10.0.2.5, server: , request: "��������H��`�Ǭֻ�0�����v&�cr.���)�WSa��8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.5 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03H\xF5\xDB`\x8F\xC7\xAC\xD6\xBB\xFF0\x07\xB6\xEA\xC7\xFEv&\xE8cr.\xFA\x06\x8A)\xB1WSa\xEA\x9A\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *11 client sent invalid method while reading client request line, client: 10.0.2.5, server: , request: "�������������zzV*����#.�����_��h����p���8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.5 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\xCA\xDD\xCF\xEE\xBBzzV*\xFF\x02\x86\x8B#.\xFC\xCD\xE0\x99\xC1_\x1D\xCAh\x1F\x10\xE7\xA3p\x85\xFF\x04\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *12 client sent invalid method while reading client request line, client: 10.0.2.52, server: , request: "���������F���F.�����0�}�z}Ţ��o���6I�@8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.52 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\xCCF\x82\xD4\xEBF.\xA7\xFC\x18\xA2\xD50\x90}\x0C\xACz}\xC5\xA2\x7F\x17o\xE8\x08\xD0\x056I\x96@\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *13 client sent invalid method while reading client request line, client: 10.0.2.5, server: , request: "���������$��>D����Iέ�e]"e��(�Hr�����ص)8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.5 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\x1E$\x8E\x18>D\x89\x85\x8C\x05I\xCE\xAD\x8Ce]\x22e\x0F\x90(\x1AHr\xD8\xE7\x9C\x17\xEA\xD8\xB5)\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *14 client sent invalid method while reading client request line, client: 10.0.2.52, server: , request: "���������5V���0Nib�Aے���T'���c�B����ॠ8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.52 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\x195V\xE0\x8B\xF70Nib\x82A\xDB\x92\x11\xF8\xFBT'\x91\xB5\xA2c\xE3B\x83\xEB\xC1\x9D\xE0\xA5\xA0\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *15 client sent invalid method while reading client request line, client: 10.0.2.52, server: , request: "���������\���4���������C,�ǘ)RU�(y���ZF8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.52 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\x93\x5C\xA0\x1F\xE64\xD7\xC8\x08\x0E\x04\x91\xF3\x95\xBF\x17C,\xED\xC7\x98)RU\x88(y\xBB\xF9\x1AZF\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
today at 4:59:09 PM2022/06/01 16:59:09 [info] 9#9: *16 client sent invalid method while reading client request line, client: 10.0.2.5, server: , request: "���������-�M•����!�����8�r������0����`E8�,�0�̨̩̪�+�/��$�(k�#�'g�"
today at 4:59:09 PM10.0.2.5 - - [01/Jun/2022:16:59:09 -0500] "\x16\x03\x01\x00\xBD\x01\x00\x00\xB9\x03\x03\x8D-\x9AM\xC2\x95\x18\xE0\xC8\xD4!\xCB\xFF\xA3\xB2\xD48\x1Ar\x9C\x9E\x95\x06\x03\xB20\x1C\x9D\xD3\xF9`E\x00\x008\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-"
from apprise-api.
Just poking around at that error at the bottom of the log, and not knowing much about coding, but was wondering if apprise uses websockets and/or node? https://stackoverflow.com/a/36522199/553663
from apprise-api.
Just poking around at that error at the bottom of the log, and not knowing much about coding, but was wondering if apprise uses websockets and/or node?
Nah, it uses neither.
What happens if you reference port 8080?
from apprise-api.
What happens if you reference port 8080?
aha! We're making progress! :) port 8080 loads the page, but the css is broken, and I get a lot of path 404's in the inspector.
today at 5:31:20 PM2022-06-01 17:31:20,349 [WARNING] django.request: Not Found: /s/js/highlight.pack.js
today at 5:31:20 PM2022-06-01 17:31:20,364 [WARNING] django.request: Not Found: /s/css/highlight.min.css
today at 5:31:20 PM2022-06-01 17:31:20,381 [WARNING] django.request: Not Found: /s/iconfont/material-icons.css
today at 5:31:20 PM2022-06-01 17:31:20,384 [WARNING] django.request: Not Found: /s/css/base.css
today at 5:31:20 PM2022-06-01 17:31:20,385 [WARNING] django.request: Not Found: /s/js/sweetalert2.all.min.js
today at 5:31:20 PM2022-06-01 17:31:20,401 [WARNING] django.request: Not Found: /s/css/materialize.min.css
today at 5:31:20 PM2022-06-01 17:31:20,407 [WARNING] django.request: Not Found: /s/js/materialize.min.js
today at 5:31:20 PM2022-06-01 17:31:20,748 [WARNING] django.request: Not Found: /s/logo.png
today at 5:31:20 PM2022-06-01 17:31:20,775 [WARNING] django.request: Not Found: /s/favicon.ico
today at 5:31:37 PM2022-06-01 17:31:37,141 [WARNING] django.request: Not Found: /s/css/base.css
today at 5:31:37 PM2022-06-01 17:31:37,141 [WARNING] django.request: Not Found: /s/iconfont/material-icons.css
today at 5:31:37 PM2022-06-01 17:31:37,513 [WARNING] django.request: Not Found: /s/css/highlight.min.css
today at 5:31:37 PM2022-06-01 17:31:37,514 [WARNING] django.request: Not Found: /s/css/materialize.min.css
from apprise-api.
Strangely, when I use port 8000 w/out the RP and go directly to the IP, i get all the css. As a test when I set that to port 8080 and go to the direct ip I get the same result as when using a RP (no css).
from apprise-api.
Well the good news from your test is you're routing correctly to the right service. Port 8080 is the Django web instance. Port 8000 is the small nginx server in front of it to serve static files.
So perhaps something in my nginx configuration is breaking things for you: https://github.com/caronc/apprise-api/blob/master/apprise_api/etc/nginx.conf
from apprise-api.
I updated the master branch; so you should be able to use :edge
with Docker soon (it's building things now i believe).
from apprise-api.
It worked! Thank you so much @STaRDoGG ! And Thank you @caronc for also helping to diagnose ! :D
from apprise-api.
Related Issues (20)
- docker compose error HOT 2
- Add Prometheus Metrics HOT 1
- Does the api support ntfy file attachments? HOT 10
- django.request: Failed Dependency Explanation HOT 4
- receiving outside web hook messages HOT 19
- Signal using curl: django.request: Failed Dependency: /notify/apprise HOT 6
- Errors in the CURL examples in configuration overview HOT 2
- Telegram: Is there a way for it to ignore all tags? HOT 13
- Webinterface Notification panel report "Bad Attachment" when none as been chosed HOT 5
- Bad Request: /notify/apprise in Docker HOT 2
- A typo in apprise-api website HOT 4
- Refactor General Display of Loaded URLs HOT 11
- Bad attachment warning for attachments > 10 MB HOT 8
- Can I customize or map [title] and [body] these two request parameters? HOT 8
- How do I mount configuration for topics properly in persistent way, so it just works? HOT 3
- Default config ID length too long HOT 2
- [Error] Bad Request: can't parse entities HOT 3
- Trying to set up API in Photon HOT 8
- Client closed connection while waiting for request HOT 1
- Stateful Configuration File Usage HOT 12
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from apprise-api.