Error Static file referenced by handler not found: dist/api/landing for Angular App deployed on Google Cloud - html

please help, I do not have experience deploying, I have been trying for days, bear with me. Thanks.
I have been working on a angular app with flask backend and both work proper locally, I need to deploy them. The server is written in flask and it is accessible via Postman. The page renders properly from "https://apt-trainer-279210.uc.r.appspot.com/" but on API call an error 404 not found when calling "api/landing" to my server. Going to the logs on GAE I see error.
Static file referenced by handler not found: dist/api/landing
I am guessing that its looking for file in the above path but it should be calling my server instead. Below is my app.yaml file for angular:
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
static_files: dist/index.html
upload: dist/index.html
- url: /
static_dir: dist
skip_files:
- e2e/
- node_modules/
- src/
- coverage
- ^(.*/)?\..*$
- ^(.*/)?.*\.json$
- ^(.*/)?.*\.md$
- ^(.*/)?.*\.yaml$
- ^LICENSE
Also note that in the angular app I proxy to the server:
{
"/api": {
"target": "http://civil-planet-279210.uc.r.appspot.com" ,
"secure": true,
"logLevel": "debug",
"changeOrigin": true,
"pathRewrite": {
"^/api/*": ""
}
}
}
A Similar question was also posted but the user was using Cloud Endpoints while my server is in python flask. I could not use the solution.
Not sure if I should post the app.yaml for the python server as it is working properly.
Your assistance would be greatly appreaciated.

According to my understanding this is working as expected. According to the documentation about header element we may find in url part:
The URL pattern has some differences in behavior when used with the following elements:
static_dir
Uses a URL prefix. The regular express pattern should not
contain groupings when used with the static_dir element. All URLs that
begin with this prefix are handled by this handler, using the portion
of the URL after the prefix as part of the file path.
So calling .../api/landing will use the same logic: " using the portion of the URL after the prefix as part of the file path."
I am not sure what is your intention, but I think you should create the handler for the feature you want to invoke.
BTW you are using Python 2 which is not already not recommended and not supported. I would consider migration. You can see this at top of every page of documentation.

Was able to fix the issue with the following yaml - I was missing the third handler.
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
static_files: dist/index.html
upload: dist/index.html
- url: /
static_dir: dist
- url: /.*
script: auto
secure: always
redirect_http_response_code: 301
skip_files:
- e2e/
- node_modules/
- src/
- coverage
- ^(.*/)?\..*$
- ^(.*/)?.*\.json$
- ^(.*/)?.*\.md$
- ^(.*/)?.*\.yaml$
- ^LICENSE

Related

Can't Define Services in CAS Overlay Template v. 6.4 (Docker)

Using the cas-overlay-template, I am trying to access the CAS login screen from HTTP(s)://localhost/admin:
https://localhost:8443/cas/login?service=https%3A%2F%2F0.0.0.0%2Fadmin
To do this, I am trying to define services inside /etc/cas/services/services.json:
{
"#class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^http://.*",
"name" : "http_services",
"allowed": true,
"ssoEnabled": true,
"anonymousAccess": false,
"id" : 1,
"evaluationOrder" : 1
},
{
"#class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^https://.*",
"name" : "https_services",
"allowed": true,
"ssoEnabled": true,
"anonymousAccess": false,
"id" : 2,
"evaluationOrder" : 2
}
FWIW, I've also tried to define a service file according to the pattern described here.
In /etc/config/cas.properties, I have defined the following:
cas.server.name=https://cas.example.org:8443
cas.server.prefix=${cas.server.name}/cas
cas.service-registry.json.location=classpath:/services
logging.config=file:/etc/cas/config/log4j2.xml
Finally in build.gradle, I have added the support for JSON service registry:
dependencies {
...
implementation "org.apereo.cas:cas-server-support-json-service-registry:${casServerVersion}"
}
No matter what I do, after building and running the Docker image, I always get the same thing:
INFO [org.apereo.cas.services.AbstractServicesManager] - <Loaded [0] service(s) from [JsonServiceRegistry].>
When I go to the URL, I am told
"Application Not Authorized to Use CAS".
What am I doing wrong?
Bonus question: https://cas.example.org:8443 does not work in the URL. Do I need to edit something in the docker container to get this to map onto my local machine?
-- UPDATE --
As was said in the answer, I needed to create a single, named service:
// File: /etc/cas/services/today-12345.json
{
"#class":"org.apereo.cas.services.RegexRegisteredService",
"serviceId":"^(https|http|imaps)://.*",
"name":"today",
"id" :12345
}
To part 2 of Misagh's answer, based on what I'm seeing in the Dockerfile, the /etc/cas/services directory simply doesn't exist by the time ./gradlew runs, and so the services aren't registered.
If I put in my cas.properties file
cas.service-registry.json.location=/etc/cas/services
I get a stacktrace that includes:
Caused by: java.io.FileNotFoundException: class path resource [etc/cas/services] cannot be resolved to URL because it does not exist
If I /bin/sh into the container, I can see the service inside of the /etc/cas/services directory.
I've been getting around this by simply copying the .json file after the Docker containers have been built
docker cp ~/emu/cas-overlay-template/etc/cas/services/today-12345.json [CONTID]:/tmp/services
(/tmp/services because that's where the console output says it's watching for services)
-- SOLUTION --
The path had to be:
cas.service-registry.json.location=file:/etc/cas/services
What am I doing wrong?
Multiple things.
You have your services in /etc/cas/services/services.json as a single JSON file. That is not correct. You need to have 1 file per 1 app. Consult the documentation for JSON service registry.
cas.service-registry.json.location should point to the directory location where such JSON files are found. You need to make sure this location in your Docker setup points or contains your service definitions.
I know I'm a bit late but I think the location /etc/cas/services it is defined in the apereo cas standalone profile. If you define another spring profile it will look for /tmp/services. It happened to me while configuring cas in docker environment and wanting to use a test profile.

Change swagger host and port serving it statically

Inspired by this sample repository, I'm generating a swagger output in json with protoc and serving it. However, for certain reasons I'm hosting the swagger content on a different port(:10000) than my REST api service(:8000).
I'm using the Go library statik to bundle up the swagger assets and serve them. It works, and a webpage is served when going to localhost:10000.
However, every cURL request swagger makes seems to be confined to just that - localhost:10000. The REST API lives on localhost:8081.
Serving swagger-ui with static content, how do I change the host/port for the REST api server?
I've tried going into the index.html of the swagger-ui content to add basePath as here, but with no luck. Every request is still made to :10000
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "./service.swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
// I added this, but it did not change anything.
basePath: "localhost:8081"
})
// End Swagger UI call region
window.ui = ui}
</script>
Add host with value localhost:8081
Remove basePath, basePath is used to change the relative path after host i.e if your web server is hosted at /v1/ etc, then you can use basepath to change that
i am still trying to find out how to pass host value dynamically for production, stage, dev env

Springdoc with multiple api-docs

I want to group three API docs in one swagger-ui. I use Springdoc. Each of the three API-docs has its own url. (They are not in the same project).
Is there a way to do this?
Edit: It's now working this way:
springdoc:
swagger-ui:
path: /
urls:
- name: App1
url: http://app1.domain.com/v3/api-docs
- name: App2
url: http://app2.domain.com/v3/api-docs
- name: App3
url: http://app3.domain.com/v3/api-docs
The answer is already available on the F.A.Q:
https://springdoc.org/faq.html#how-can-i-agreagte-external-endpoints-exposing-openapi-3-spec-inside-one-single-application
The properties springdoc.swagger-ui.urls.*, are suitable to configure external (/v3/api-docs url):
For example if you want to agreagte all the endpoints of other services, inside one single application. Don’t forget that CORS needs to be enabled as well.
Details of the properties are available here:
https://springdoc.org/springdoc-properties.html

carrierwave-aws: Rails API app file upload fails with NoMethodError - undefined method `match' for nil:NilClass

Hitting quite the wall on this issue. Let me explain what i've done and show the snippets of configured code, to hopefully find a solution
Ruby: 2.4.0
Rails: 5.x
Gems (specific to this):
- carrierwave 1.2.3
- carrierwave-aws
Here is the error
NoMethodError - undefined method `match' for nil:NilClass:
app/controllers/api/v3/video_controller.rb:23:in `upload'
Here is my config/environments/carrierwave.rb file
CarrierWave.configure do |config|
config.storage :aws
config.aws_credentials = {
provider: "AWS",
aws_access_key_id: Rails.application.secrets.aws_access_id,
aws_secret_access_key: Rails.application.secrets.aws_access_secret,
region: "us-east-1"
}
config.aws_bucket = "{{BUCKET_NAME_HERE}}"
end
Here is my uploader
class VideoUploader < CarrierWave::Uploader::Base
storage :aws
end
Finally, here is how i'm calling the upload, since it's an API, i'm not using a form builder or model assignment.
def upload
video = params[:video]
if video
# Send file to Amazon S3 bucket and grab URL
uploader = VideoUploader.new
uploader.store!(video.tempfile)
# uploader.retrieve_from_store!(tempfile_name)
# logger.info uploader.download_url(video.original_filename)
end
end
I've tried carrierwave + fog, fog-aws. When I remove the S3 equation the file will be stored locally (development machine). I am at my wits end with trying lib/ hacks, downgrading versions. I hope its a simple oversight but am out of ideas.
Any help is greatly appreciated!
Fixed! The problem was pretty stupid and man I wish I caught it sooner. The initializer file was in the environments directory (I even listed it in my question!), not the initializers directory... don't code on an empty stomach.
Would be great if the code could detect that missing file... but at least its solved.

AngularJS + GAE not updating HTML

EDIT: Turns out the version being served was outdated - updating the version in app.yaml doesn't actually update the served version.
As the title says, I'm trying to upload changes to an AngularJS app to Google App Engine (Python, if it matters).
The referenced HTML files for each view however will not update and I'm not sure why.
Here's the app.yaml:
- url: /site/(.*\.(js|css|png|ico|txt))$
static_files: site/dist/\1
upload: site/dist/.*\.(js|css|png|ico|txt)$
login: required
secure: always
- url: /site/(.*\.html)$
static_files: site/dist/\1
upload: site/dist/.*\.html$
login: required
secure: always
expiration: '30s'
- url: /site/.*
static_files: site/dist/index.html
upload: site/dist/index.html
login: required
secure: always
And a couple of examples of HTML referenced in app.js:
// Routes
$routeProvider
.when('/users', {
templateUrl: 'users/users.html',
controller: 'UserCtrl',
activeTab: 'users',
reloadOnSearch: false
})
.when('/users/profile/:userId', {
templateUrl: 'users/profile.html',
controller: 'UserProfileCtrl',
activeTab: 'users'
})
.when('/users/new', {
templateUrl: 'users/create.html',
controller: 'UserCreateCtrl',
activeTab: 'users'
})
So the html is in dist/users/__.html or appropriate, with app.js residing under dist/
Updating these files, then doing a GAE update does not update the html. I've set a cache expiration of 30s, still not updating.
Is there anything I can do to force all html changes to be uploaded?
JS/CSS files have a version number appended to the end as part of the build process so they work fine, but as far as I can tell that's not possible to do for the html with angular routes.
Perhaps you previously had a longer cache setting for the .html files? In that case they could already be cached on the Google frontend servers. If you look at the response headers in your browser's network inspector you can see if they are indeed cached and perhaps what their age is. You might have to wait till they are evicted from the cache before you can see updates to them again.
In the mean time, try with different filenames and see if that does work.
Another trick you could try is to add a timestamp to the filename.
So instead of requesting 'users.html' you could request 'users.html?cachebuster=' + +new Date()