Akka http unsupported method exception - http

I have a plain http route defined like so
delete {
handleErrorsAndReport("delete_foo") {
fooRepository.deleteFoo(fooId)
complete(NoContent)
}
}
I wanted to add some basic authentication to it so now it looks like
seal(
authenticateBasic(
realm = "Secure foo",
scopeAuthenticator
) { scopes =>
delete {
handleErrorsAndReport("delete_foo") {
fooRepository.deleteFoo(fooId, scopes)
complete(NoContent)
}
}
}
)
The full directive is
concat(
get {
// something else which is working
},
seal(
// something else which is working
),
seal(
authenticateBasic(
realm = "Secure foo",
scopeAuthenticator
) { scopes =>
delete {
handleErrorsAndReport("delete_foo") {
fooRepository.deleteFoo(fooId, scopes)
complete(NoContent)
}
}
}
)
)
Now I am getting the following exception when I am trying to delete foos
Request DELETE http://builder/foos/fooId failed with response code 405 due to request error. Response body: HTTP method not allowed, supported methods: PUT
What could be the issue? The way I've been consuming the API has not changed but I'm afraid that something has changed with the introduction of the seal directive.

I have no idea why but this worked
concat(
get {
// something else which is working
},
seal(
authenticateBasic(
realm = "Secure foo",
scopeAuthenticator
) { scopes =>
concat(
delete {
handleErrorsAndReport("delete_foo") {
fooRepository.deleteFoo(fooId, scopes)
complete(NoContent)
},
put {//other authenticated endpoint}
)
}
}
)
)
In other words, I consolidated the two sealed directives which were before separate. Maybe it's related to this

Related

Convert Discord.js v11 module to v12?

I mostly have this discord bot working. I am just having some trouble with this one module. The root of the problem is that this code was written for discord.js v11. I need to rewrite it for v12.
The original v11 module can be found here:
https://github.com/Meschdog18/disnet/blob/master/commands/broadcast.js
Here is what I have thus far:
exports.run = (client, message, args) => {
var serverlist = client.guilds.cache.size;
console.log(client.Networks)
var server = message.guild.channels.cache;
var Sender = client.Networks.get(message.guild.name);
const input = args.join(" "); //rejoins arg array into string
for (var i = 0; i < serverlist.length; i++) {
//get network id of message sender
var Recipient = client.Networks.get(serverlist[i].name);
Recipient = parseInt(Recipient);
if (Sender == Recipient) {
try {
var serv = serverlist[i].channels.cache.find(
serv => serv.name === "broadcast"
);
serv.send({
embed: {
/* author: { works but is disabled, because not sure if i like the look
name: "Disnet",
icon_url: client.user.defaultAvatarURL
},*/
color: 0x3850eb,
title: "**__BROADCAST__**",
thumbnail: {
url: message.guild.iconURL
},
fields: [{
name: "Broadcasted From ",
value: message.guild.name
}, {
name: "Message",
value: input
}
],
timestamp: new Date(),
footer: {
icon_url: message.author.avatarURL,
text: "Executed By " + message.author.username
}
}
})
} catch (error) {
console.log(error);
message.reply(
"You must create a #broadcast channel to recieve messages!"
);
break;
}
}
}
};
exports.help = {
name: "broadcast",
description: "Broadcasts message to all servers on your network",
usage: "N$broadcast <Message>"
};
exports.config = {
permLevel: "admin"
}
This module is meant to have the bot transmit a message to every server in my network of discord servers. (it does use enmap and MySQL, but this module doesn't appear to use the SQL component(s))
It is not transmitting messages to the other servers in my network, but I am not getting any errors thrown in my terminal. The bot just gives me this:
Enmap(2) [Map] {
'Discord Sports & Athletics Associations' => 'DSAAnet',
'NFL Discussion 2.0' => 'DSAAnet'
}
Which appears to be correct. (DSAAnet is the name of the network, and the other two names are names of servers in the network.)
Is this correct? What else do I need to change to make this v12 compatible?
you can see every change on this website: Updating from v11 to v12
I think you were reading this part.
Collection#filterArray
collection.filterArray() was removed entirely, as it was just a helper method for collection.filter().array() and most of the time converting a collection to an array is an unnecessary step.
No, .array() was never ever removed.
And for your question, it says .avatarURL, .iconURL, .defaultAvatarURL is now .avatarURL(), .iconURL(), .defaultAvatarURL()
That should fix the issue :)

Component method fails to assign data that has not yet been fetched by the service

officeView.component.ts
setSelectedPerson(id:number)
{
this.pservice.getPerson(id);
localStorage.setItem("selectedPerson", JSON.stringify(this.pservice.person));
}
person.service.ts
getPerson(id:number)
{
this.http.get(personUrl + id).subscribe(response => this.person = response )
}
person:Person;
I'm executing setSelectedPerson method from OfficeViewComponent and here's what I'm hoping to happen:
I ask PersonService to fetch the data from api and assign it to it's variable - PersonService.person;
Now that the response is assigned to the service person variable, I'm expecting it to be stringified and saved in localStorage.
But here's what actually happens:
I ask PersonService to fetch the data, PersonService reacts and proceeds with the request, but by the time PersonService.getPerson() is finished, localStorage has already attempted to collect the data from PersonService.person, which - at that time - was unassigned.
I know there is a way to wait until the service method finishes it's work, but I don't know exactly what should I use.
Return the subscription from the service and use it to set data inside it. You don't need any variable inside your service.
officeView.component.ts :
setSelectedPerson(id:number){
this.pservice.getPerson(id).subscribe(
response => {
localStorage.setItem("selectedPerson", JSON.stringify(response));
},error => {
console.log('Error :',error.error)
}
)
}
person.service.ts :
getPerson(id:number) : Observable<any>{
return this.http.get(personUrl + id);
}
You're right, you should wait until the result is ready.
By then you can call the setSelectedPerson func.
//service func
getPerson(id:number) {
return this.http.get(personUrl + id);
}
//component func
setSelectedPerson(id:number){
this.pservice.getPerson(id).subscribe(data => {
localStorage.setItem("selectedPerson", JSON.stringify(data ));
});
}
The problem with you code is the early subscribe in service itself, Ideally it should be in the component (at the caller)
officeView.component.ts :
setSelectedPerson( id : number ){
this.pservice.getPerson(id).subscribe(
response => {
localStorage.setItem("selectedPerson", JSON.stringify(response));
},error => {
console.log( 'Error :',error.error )
}
)
}
person.service.ts :
getPerson( id : number ) : Observable< any >{
return this.http.get( personUrl + id );
}
person.service.ts
getPerson(id:number) {
return this.http.get(personUrl + id);
person:Person;
and when you calling the HTTP service you should use subscribe
setSelectedPerson(id:number){
this.pservice.getPerson(id).subscribe(data=>{
console.log(data);
});
}

Settings HTTP output header parameters working with aggregation

I am trying to change the contentType from the response of an aggregated operation, here is my example code.
interface MyAggregateInterface {
RequestResponse:
op1(typeOp1Request)(typeOp1Response)
}
outputPort MyAggregatePort {
Interfaces: MyAggregateInterface
}
embedded {
Jolie:
"MyAggratedCode.ol" in MyAggregatePort
}
inputPort MyInputPortHttp {
Protocol: http {
.debug= 1;
.debug.showContent =1;
.format -> format;
.contentType -> mime;
.charset ="UTF-8";
.default = "default";
.compression = false
}
Location: "socket://localhost:8081"
Interfaces: DefaultHttpInterface
Aggregates: MyAggregatePort
}
I would like to change the return format for op1.
well I will try to answer your question
we need to define your op1 response type
type typeOp1Response:any{
.format?:string
}
or if you prefer
type typeOp1Response:undefined
I personally prefer the first one so that you can decide the mime in the aggregated service
Now you need to add a courier sessions
courier MyInputPortHttp {
[interface MyAggregateInterface( request )( response )]{
forward( request )( response );
if (is_defined(response.format)){
mime = response.format;
undef(response.format);
}
}
This implementation has a limitation that can return flat data in the root node
Another way is to use the inputType to define your output format.
type typeOp1Request:void{
.otherParameter1:string
.format?:string
}
then your courier
courier MyInputPortHttp {
[interface MyAggregateInterface( request )( response )]{
forward( request )( response );
if (request.format=="json"){
mime = "application/json"
};
if (request.format=="xml"){
mime = "application/xml"
};
}
Not sure if this answers your question
As Balint pointed out, we are missing some information on the nature of the response.
However, it seems to me that the second example better covers the general case. We abstract from any information coming from the aggregated service (which ignores the fact it is aggregated) and we decide what to do with the response, based on local logic (within the aggregator).
Following Balint's example, we can wrap the aggregated operation with a courier and define the format of the output there. I include below a minimal working example.
Aggregated service
type PersonRequestType: void {
.name: string
}
type PersonResponseType: void {
.name: string
.surname: string
}
interface MyAggregatedInterface {
RequestResponse: op1( PersonRequestType )( PersonResponseType ) throws RecordNotFound
}
inputPort IN {
Location: "local"
Interfaces: MyAggregatedInterface
}
execution { concurrent }
main
{
op1( request )( response ){
if( request.name == "Mario" ){
response.name = "Mario";
response.surname = "Mario"
} else {
throw ( RecordNotFound )
}
}
}
Aggregator service
include "aggregated.ol"
outputPort MyAggregatePort { Interfaces: MyAggregatedInterface }
embedded { Jolie: "aggregated.ol" in MyAggregatePort }
inputPort HttpPort {
Location: "socket://localhost:8000"
Protocol: http {
.format -> format
}
Aggregates: MyAggregatePort
}
courier HttpPort {
[ interface MyAggregatedInterface( request )( response ) ]{
forward( request )( response );
format = "json" // e.g., alternative xml
}
}
By changing the value set to format, e.g., from "json" to "xml", we change the format of the HTTP response.
References:
Courier sessions in the Jolie documentation
Reference introduction of couriers and detailed example of its semantics, Pre-print version, https://doi.org/10.1109/SOCA.2012.6449432

Why 404.html causes uncaught error during service worker caching?

I have implemented service worker in my web app and attempted to cache all html, css, js, and images file. My hosting service is firebase, after a successful deployment I tested if the service will work and the files will be cached, unfortunately the following error will do occur.
service-worker.js
let cacheName = 'my-tools-v1';
let filesToCache = [
'/',
'/css/app.css',
'/css/diffview.css',
'/css/json-lint.css',
'/css/materialize.css',
'/images/favicon.png',
'/images/icons/apple-touch-icon.png',
'/images/icons/apple-touch-icon-57x57.png',
'/images/icons/apple-touch-icon-72x72.png',
'/images/icons/apple-touch-icon-76x76.png',
'/images/icons/apple-touch-icon-114x114.png',
'/images/icons/apple-touch-icon-120x120.png',
'/images/icons/apple-touch-icon-144x144.png',
'/images/icons/apple-touch-icon-152x152.png',
'/images/icons/apple-touch-icon-180x180.png',
'/images/icons/icon-72x72.png',
'/images/icons/icon-96x96.png',
'/images/icons/icon-128x128.png',
'/images/icons/icon-144x144.png',
'/images/icons/icon-152x152.png',
'/images/icons/icon-192x192.png',
'/images/icons/icon-384x384.png',
'/images/icons/icon-512x512.png',
'/js/index.js',
'/js/css-lint.js',
'/js/difflib.js',
'/js/diffview.js',
'/js/ipsum-generator.js',
'/js/json2.js',
'/js/json-lint.js',
'/js/jsonlint.js',
'/js/lorem-ipsum.js',
'/js/materialize.js',
'/js/visual-difference.js',
'/bower_components/codemirror/lib/codemirror.js',
'/bower_components/codemirror/mode/javascript/javascript.js',
'/bower_components/codemirror/mode/css/css.js',
'/bower_components/codemirror/addon/edit/matchbrackets.js',
'/bower_components/codemirror/addon/comment/continuecomment.js',
'/bower_components/codemirror/addon/comment/comment.js',
'/bower_components/ft-csslint/dist/csslint.js',
'/bower_components/jquery/dist/jquery.slim.min.js',
'/bower_components/kanye-ipsum/dist/jquery.kanye-ipsum.min.js',
'/bower_components/codemirror/lib/codemirror.css',
'/index.html',
'/css-lint.html',
'/ipsum-generator.html',
'/json-lint.html',
'/visual-difference.html',
'/notfound.html',
'/404.html'
];
self.addEventListener('install', (e) => {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then((cache) => {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', (e) => {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map((key) => {
if (key !== cacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
});
self.addEventListener('fetch', (e) => {
console.log('[ServiceWorker] Fetch', e.request.url);
e.respondWith(
caches.match(e.request).then((response) => {
return response || fetch(e.request);
})
);
});
Then all files were not cached because of this. But if I remove the 404.html or rename it to other name the service worker will work fine and all files will be cached. It is also weird that in my local server the service worker works and caches 404.html but it fails in firebase.
Why 404.html causes uncaught error during service worker caching? How do I resolve this?
Cache.addAll() is an all or nothing API. If any response is not in the 200 HTTP status code range, nothing will be cached.
cache.addAll will reject if any of the resources fail to cache. This means the service worker will only install if all of the resources in cache.addAll have been cached.
Firebase returns 404 Not Found for the /404.html file.
An approach to resolve this is to have a file /notfound.html like you have and then return that in fetch when needed.
You cannot add 404 error html page into cache, if it returns 404 https status (as it should).
But still you can create 404 error page with service worker and use it for sites not in cache even if website is in offline mode.
Using catch() after fetch() request and create whole new Response
minimalistic example:
// self is ServiceWorkerGlobalScope
self.addEventListener( 'fetch', function ( /** #type {FetchEvent} */ event )
{
//const caches = ( event.target.caches );
event.respondWith(
caches.match( event.request ).then( ( /** #type {Response | undefined} */ response ) =>
{
if ( response ) {
return response;
}
return fetch( event.request.clone() ).then( ( /** #type {Response} */ response ) =>
{
//…
return response;
}
).catch( () =>
{
return new Response( '<h1>404 - Not found</h1><p>more HTML here …</p>', {
status: 404,
statusText: 'Not found',
headers: new Headers( {
'Content-Type': 'text/html'
} )
} );
} );
}
)
);
} );

Hardcoded manifest start url still not found?

I am attempting to setup a WordPress Theme as a Progressive Web App. When I run Chromes Audit tool (lighthouse?) I get an uninformative error that I don't know what exactly the problem is. The error is:
Failures: Service worker does not successfully serve the manifest start_url. Unable to fetch start url via service worker
I have hardcoded my start url which is a valid url. Any suggestions on what the issue could be?
https://mywebsite.com/wp-content/themes/mytheme/web.manifest:
...
"scope": "/",
"start_url": "https://mywebsite.com",
"serviceworker": {
"src": "dist/assets/sw/service-worker.js",
"scope": "/aw/",
"update_via_cache": "none"
},
...
}
https://mywebsite.com/wp-content/themes/mytheme/dist/assets/sw/service-worker.js:
...
// The fetch handler serves responses for same-origin resources from a cache.
// If no response is found, it populates the runtime cache with the response
// from the network before returning it to the page.
self.addEventListener('fetch', event => {
// Skip cross-origin requests, like those for Google Analytics.
if (event.request.url.startsWith(self.location.origin)) {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return caches.open(RUNTIME).then(cache => {
return fetch(event.request).then(response => {
// Put a copy of the response in the runtime cache.
return cache.put(event.request, response.clone()).then(() => {
return response;
});
});
});
})
);
}
});
I register my SW with the following code and it outputs that it has successfully registered the SW:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(Vue.prototype.$ASSETS_PATH + 'sw/service-worker.js')
.then(function(registration) {
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
console.log('Service worker registration failed, error:', error);
});
}
Please change your start_url to
"start_url": "/"
It has to be a relative url. Please see the documentaion

Resources