CORS Fastapi Problem in dockerized deployment to Digital Ocean - docker

I have deployed my first webapp at a digital ocean droplet.
The app has two docker containers running at :8000 and :5173
It has a frontend and a backend.
Originally I thought Cors is not enabled.
However after more research I think the issue lies with Fastapi as I've found other threads with similar problems.
Unfortunately none worked. There is talk on github and SO that fastapi and docker is the problem, but it works fine on my local machine. (in the container).
I tried these, this and pretty much everything I could find.
The error message is:
Access to fetch at 'http://<IP address>:8000/mdstats_player' from origin 'http://<IP address>:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
GET http://<ip_address>/mdstats_player net::ERR_FAILED 200
In Fastapi I set up the allowed origins including that new IP address.
Exactly like https://fastapi.tiangolo.com/tutorial/cors/ and it works locally originally getting the same error.
I also tried the wildcard and starlette.
I can access http://<ip_address>:8000 just fine.The container is running as expected.
On my local machine everything works as expected too. (i.e. backend and frontend containers can communicate).
The origins I set, (where ipaddress is my Digital Ocean IP address), the exact same one that gets denied, I think I have all variations, but maybe I am missing one?
origins = [
"http://localhost:5173",
"localhost:5173",
"http://<ip_address>:5173",
"<ip_address>:5173",
"http://<ip_address>:5173/",
"localhost:5173/",
"0.0.0.0:5173",
"http://172.18.0.2:5173/",
]
As a last chance:
I am also using svelte with vite.
In my docker-compose file I set:
- VITE_BACKEND_URL=http://<ip_address>:8000
original set to localhost
Many thanks in advance.

After trying pretty much everything I have found a solution:
instead of adding the middleware afterwards like they do on the fastapi tutorial
I did this:
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware import Middleware
app = FastAPI(middleware=middleware)
origins = [
"http://localhost:5173",
"http://localhost:5173/",
"localhost:5173",
"localhost:5173/",
"0.0.0.0:5173",
"http://172.18.0.2:5173/",
"http://192.168.64.2:5173/",
]
middleware = [
Middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*']
)
]
I also had to add the network ips.
But the middleware part was crucial. Even with the network ips with app.add_middle_ware this won't work. I tried several times just to make sure that really is the solution since it seems like a lot of the other posts that come across have solutions that were just along the way since docker doesn't update everything each system update. See issues of docker on github.
Hope this helps someone. What insanity.

Related

Add a URL path prefix to artifactory installation (Docker)

I'm running Artifactory CPP CE 7.7.3 and Traefik v2.2 using docker-compose. The service is only available over http://localhost/ui/. Now, what I need is an option which allows to add a URL path-prefix (e. g. http://localhost/artifactroy/ui).
My Setup
I used the described setup process from the Artifactory Docs suggest it.
My docker.compose.yaml is the official extracted from the jfrog-artifactory-cpp-ce-7.7.3-compose.tar.gz: ./templates/docker-compose.yaml.
I'm using a reverse proxy (traefik). For this, I've added the necessary traefik configuration lines to the docker-compose-file. Here is a small extract what I've added:
[...]
labels:
- "traefik.http.routers.artifactory.rule=Host(`localhost`) && PathPrefix(`/ui`)"
- "traefik.http.routers.artifactory.middlewares=artifactory-stripprefix"
- "traefik.http.middlewares.artifactory-stripprefix.stripprefix.prefixes=/"
- "traefik.http.services.artifactory.loadbalancer.server.port=8082"
With this I managed to access artifactory over http://localhost/ui/.
Problem:
I have multiple small services running on my server, each of this service is accusable via http://localhost/<service-name>. This is very convenient and want to make clear that this URL is related to this service on my production server.
Because of this, I want to have an URL like http://localhost/artifactroy/ui/... instead of http://localhost/ui/...
I struggled getting artifactory setup in that way. I already managed to get a redirection from typing e. g. http://localhost/artifactroy/ to http://localhost/ui/ but this is not what I want on my production server.
What I did
Went through the documentation in hope of finding an option which I just can passt to artifactroy to add a prefix (Not successful).
Tried configure traefik two full days, to alter headers to get the repose point to http://localhost/artifactroy/ui/... (Only partially successful, redirection didn’t work afterwards)
Tried finding the configuration which is responsible for configure artifactory in $JFROG_HOME/artifactory/var/etc (Not successful)
Is this even possible? Help is highly appreciated..
This example (even though not traefic example) gives you a direction to implement it. There are certain routes already used within the product. You need to add a context over and above it to ensure all comes via the new context path.
https://jfrog.com/knowledge-base/how-to-remove-artifactory-from-the-context-url-in-artifactory-7/

ipRestrictions not working in Grails 3.3.10?

I can't get ipRestrictions to work via springsecurity.
I'm working with a bare app to try and isolate the issue with Grails 3.3.10 and spring-security-core 3.2.0.
Eventually I want to restrict access to a web service to a limited subnet. But in an attempt to get this to work I'm just trying to find any case that will get rejected.
I'm working with a stock create-app application but I've added the following to build.gradle to pull in spring-security:
compile 'org.grails.plugins:spring-security-core:3.2.0'
My application.groovy to configure this is:
grails.plugin.springsecurity.rejectIfNoRule = false
grails.plugin.springsecurity.fii.rejectPublicInvocations = false
grails.plugin.springsecurity.ipRestrictions = [
[pattern: '/**', access: '172.16.0.1']
]
I'm expecting to see something like a 401 Unauthorized or 403 Forbidden.
IP Address Restrictions don't apply to requests coming from localhost. This is to "help" local development but subsequently makes testing your restrictions more difficult. There is a confusingly worded note at the bottom of section 18 of the docs that should start "All patterns can always be accessed from localhost regardless of IP address":
All addresses can always be accessed from localhost regardless of IP pattern, primarily to support local development mode.

Is it possible to share my localhost with someone on a different network?

I am working with a designer and I'd like them to have access to the interactions I've implemented on the site we're working on. However this time, I have 2 issues. My localhost is configured to a subdomain:
http://store.teststore:3000/ and we're on different networks. Is there anyway to work around this?
ngrok should work for you. Download and install it following these instructions here: https://ngrok.com/download. Documentation on how it is used can be found here https://ngrok.com/docs. Once installed running the below command should work for you (depending on the hosting environment):
ngrok http -host-header=rewrite store.teststore:3000
You will need to give the URL generated by ngrok and displayed in the cmd prompt to the designer.
Update: Handling absolute redirects
Based on your comment it sounds like, after login, your site does an absolute redirect (the full URL is specified). If it is possible I would change your code to do a relative redirect where the domain is omitted. You could also make your root domain configurable in the absolute redirect and configure it to be the ngrok domain provided for now. Lastly, you could attempt to configure your DNS with a CNAME record following ngroks Tunnels to custom domains documentation. This last option, however, requires a paid for ngrok subscription.
Install ngrok if you haven't yet and CD into your project directory and invoke ngrok. Note Your application must be running locally on the same port number ngrok will be running.

Traefik/Docker/Wildfly - Cannot access Wildfly management console

I'm running Traefik in a Docker container, with Wildfly in other container.
I have the following labels in Wildfly's docker-compose.yml:
- "traefik.web.port=8080"
- "traefik.web.frontend.rule=Host:temporary_wildfly_hostname"
- "traefik.admin.port=9990"
- "traefik.admin.frontend.rule=Host:temporary_wildfly_hostname;PathStrip:/console/"
I can access the main Wildfly, which is in port 8080. I've tried many ways to access the service in port 9990, but the only one which really works is when I use a different Host, which isn't what I want.
I've tried:
Added "traefik.frontend.passHostHeader=true" (even with .admin before .frontend)
Switching PathStrip with PathPrefixStrip, Path PathStripRegex or even PathPrefixStripRegex
Wildfly's management console uses port 9990, redirects from :8080/console and also uses :9990/console/*, so /console by itself is redundant and it shows "too many redirects" errors.
I really think this /console loop error is some kind of an issue. I've been searching online for alternative configurations for other reverse proxies, to see if I'm missing something, but all relate to the headers, which I've already tried.
Any hint on how can I solve this, keeping the same URL, but still redirecting to a different port than the main service?
Thanks a lot for your time and help.
Best regards,
Luis Nabais
You need to add a priority on each segment.
traefik.<segment_name>.frontend.priority=10
Thanks a lot for your answer.
The issue was related to the backend wildfly creates. It uses another URL, which is /management. So I solved it using the following traefik labels:
- "traefik.web.port=8080"
- "traefik.web.frontend.rule=Host:temporary_wildfly_hostname"
- "traefik.admin.port=9990"
- "traefik.admin.frontend.rule=Host:temporary_wildfly_hostname;PathPrefix:/console,/management"

My rack-proxy app works with different ports, but not different URLs

I wrote a little Rack app the uses rack-proxy to make it look like apps that are running on different ports are actually different subdirectories of one domain. It works.
If I'm running notes on port 3001 and photos on 3002, then I'm able to go to localhost:3000/notes or localhost:3000/photos and everything works properly.
That's only helpful for running it locally. But if I want to run this same setup on Heroku I need to be able to proxy to/from different URLs, not just different ports. So when I change my code from setting env["HTTP_HOST"] to http://localhost:3001 for /notes, to instead set env["HTTP_HOST"] to http://sbbme-note.herokuapp.com for /notes, Rack blows up on me.
I thought it would Just Work™. Unfortuntely, I'm missing something.
Errno::EADDRNOTAVAIL at /notes
Can't assign requested address - connect(2) for "http://sbbme-note.herokuapp.com" port 0
The full stack trace is in this gist.
https://gist.github.com/veganstraightedge/6d840377bf20b4b5f5db
The repo is homesteading/homesteading-router-rack. The master branch is the one working in local development mode only (multiple ports on localhost). The heroku-router branch is where I'm trying to use different (sub)domains instead of just different ports. heroku-router is the one that blows up (see gist above).
If you want to install this and try it on your own machine, this should work:
gem install homesteading
homesteading new mysite
cd mysite
homesteading server
open http://localhost:3000
I'm real close to being able to replace my years old pile of mono-rails with my constellation of apps approach in Homesteading. This router is the last main blocker. Any help would be greatly appreciated.
PS. My intial version is based on this blog post (livsey dot org/blog/2012/02/23/using-rack-proxy-to-serve-multiple-rails-apps-from-the-same-domain-and-port) and this Stack Overflow question/answer (stackoverflow dot com/questions/11057905/how-do-i-use-rackproxy-within-rails-to-proxy-requests-to-a-specific-path-to-an "How do I use Rack::Proxy within Rails to proxy requests to a specific path to another app - Stack Overflow").
Looking at the setup and the stack trace it looks like the proxy is atrying to connect to the sbbme-note app on port 0. Try adding
ENV['SERVER_PORT'] = '80'
You might also consider using the nginx build pack on heroku an implementing a forward proxy that way. I've used this build pack as a basic forward proxy and it has worked great. There are other nginx build packs that are designed to hook up to you application server (like unicorn) that might also be useful for this use.
The solution was a combination of Lukas' suggestion and fixing what I was originally doing.
I added this (as suggested by Lukas).
env['SERVER_PORT'] = 80
AND I removed the http:// from my env["HTTP_HOST"]
So, this:
env["HTTP_HOST"] = "http://#{app}"
became this:
env["HTTP_HOST"] = app
Thanks for your help, Lukas!

Resources