Is there a way for SvelteKit components to have corresponding endpoint files? - forms

I have a SvelteKit Component that needs a corresponding +page.server.ts for cookie authenticated form actions. My goal is to have a Component with a corresponding delete button that will send an API request to my backend from within a form action inside a +page.server.ts endpoint.
My structure for some clarity:
- src/
- components/
- Component/
- +page.svelte
- +page.server.ts
- routes/
- route/
- +page.svelte
Component +page.svelte:
<div class="card">
<form method="POST">
<input type="hidden" value="{uuid}" name="uuid" />
<button class="btn-icon variant-filled-primary">
<span><Icon icon="material-symbols:delete-outline"></Icon></span>
</button>
</form>
</div>
Component +page.server.ts:
import type { Actions } from './$types';
export const actions = {
default: async ({ cookies, request }) => {
// Doing some http-only Cookie authenticated fetching and data processing here
}
} satisfies Actions;
The component is being rendered as perfectly fine as it did when I was still using just Component.svelte as my structure/nomenclature without a dedicated folder and +page.svelte.
The error I'm getting from within my browser after clicking the submit button in the component goes as follows:
405 POST method not allowed. No actions exist for this page
I figured this behaviour may appear since I don't have any form actions specified for my Routes +page.svelte but for my Components +page.svelte which, for whatever reason, won't be executed when clicking the form submit button.
Is my approach to this problem even possible of a solution or am I being forced right here to roll back and just use Route Form Actions from within every single route that utilizes my component? Doesn't seem like a very scalable option to me.

One thing to keep in mind with Sveltekit is that you get a lot of "magic" in the name of keeping things easy to use and on the happy path. The whole framework is designed around that premise and makes use of conventions to get it done.
Your src/routes directory is a convention that the whole router is built around, so anything that needs to execute routing behavior out of the box needs to be inside that directory. However, you still have a large amount of flexibility in how it all gets put together. In this case you have a couple of options.
Options 1: API Routes
As people have mentioned in the comments, you can use the routes directory to build out an API structure independent of any .svelte files that will render. A common structure would be something like this, which would create a standard endpoint route:
- src/
- routes/
- api/
- delete/
- +server.js
Inside the +server.js file you can build out standard handlers for GET, POST, etc. Then you can call the endpoint as a relative path from the root path, anywhere in the app and from any component using fetch, and you can also call it from other +page.js and +*.server.js files. In this case the route is reached with the path /api/delete.
Option 2: Co-locate components with routes
Another option if the component only relates to one route is to co-locate the component in the routes directory. If it doesn't have the + prefix it will be ignored by the router. This makes the following structure valid:
- src/
- routes/
- route/
- FormComponent.svelte
- +page.svelte
- +page.server.js
- utilities.js
In this case, both the FormComponent and the utilities files are ignored by the router, but both are still accessible from other files in the route. In cases where you need to decompose pieces of a page for reuse in that page, but those pieces only apply to the route in question, this can massively simplify your dependency map between files. Note that files placed in routes using this pattern can still be used elsewhere with standard relative path imports, but if you need to access them somewhere else they are probably better off living in the $lib directory.
A note about the official docs
I have found that the official docs are complete, but are also very succinct. There isn't a lot in the way of code examples, just enough to get you going. It's a great resource for reference but it can be challenging for discovery. Also an understanding of vanilla Svelte is assumed throughout, along with an understanding of HTTP conventions and web standards.
With that in mind, asking question here is encouraged, along with the official Svelte discord community which also covers Sveltekit. I've also found the Reddit community to be very helpful.

Related

How to clear the whole AEM dispatcher cache in a cloud manager deployment

I'd like to configure the Adobe Cloud Manager production pipeline to invalidate the whole dispatcher cache. What paths do I have to give at the production pipeline dispatcher invalidation configuration to have that done? Is it possible to give a pattern here that matches everything? The page-invalidate description talks about a path-pattern, but doesn't describe what exactly that means.
We work with statfilelevel=2. It seems the .stat files are very important for that, though the description given here is unfortunately not precise enough, not sure I understand that right.
I tried to configure /content as path - that just touches /mnt/var/www/html/.stat (/mnt/var/www/html is the docroot), which seems to apply to nodes like /* but not like /content/* .
If I give /content/oursite, that touches /mnt/var/www/html/content/.stat , too, but that does seem to apply to nodes like /content/oursite or /content/othersite, but not to pages like /content/oursite/about - for which would /mnt/var/www/html/content/oursite/.stat be relevant, if I understand that right.
Do I seriously have to enumerate a page in each site that has a .stat file, or is there a more sensible way to get everything invalidated? After all, a deployment could easily change the HTML of every page if a component has changed.
If you have ACS commons installed then you can try to use this powerful feature
https://adobe-consulting-services.github.io/acs-aem-commons/features/dispatcher-flush-rules/index.html

Wicket reporting same FileUpload object in subsequent requests

I have a panel used in multiple pages in an app we're developing. In this panel is a FileUploadField that uses AjaxFormSubmitBehavior (extended as FileUploadBehavior) on "change" to upload a file, which I then add to a list via ajax, update the view, clear the FileUploadField, and then allow them to select another file. And this is in fact exactly what happens in one of the pages using the panel...but not in another. In the non-working page, the first file selected is repeated over and over regardless of what file is picked after the first.
In the onSubmit of the behavior, we get the the FileUpload object which is supposed to be different between requests. I can see in the debugger that the FileUpload is the exact same object as the previous request, not merely carrying the same payload.
I'm scrutinizing the usage of the panel on the two pages and see no material differences. I can see the file control on the page DOES show the changed file name while I sit at my breakpoint on the server (so I suspect whatever is going wrong is on the java side). But I can't figure out why they behave differently or see where it's going wrong. The panels and pages are large and complex, so here's snippets of the relevant pieces.
FileUploadBehavior.onSubmit(AjaxRequestTarget) :
FileUploadField fileUploadField = (FileUploadField) fileUploadContainer.get("fileUploadField");
FileUpload fileUpload = fileUploadField.getFileUpload();
[...]
//clear file input after each request for next upload.
fileUploadField.clearInput();
target.add(fileUploadField);
I have a break right after this line and can see the first file gets repeated. The code that instantiates the field and behavior in the panel looks like:
FileUploadField fileUploadField = new FileUploadField("fileUploadField");
fileUploadField.add(new FileUploadBehavior("change", maxFileSize).setDefaultProcessing(false));
fileUploadContainer.add(fileUploadField);
The html tag:
<input wicket:id="fileUploadField" class="form-control" type="file" id="formFile" multiple>
I feel like the fact that it works in one page and not in another leads me to think the problem is outside the panel. The fact that the control in the browser shows the 2nd filename during test leads me to think it's on the java side. But nothing about the file event or definition happens outside the panel itself. The form elements are declared identically, and both have multipart enctypes when the pages render. Both successfully upload their first file. I'm kind of not even sure where to look for why wicket is re-using the FileUpload object in one page but not in another.
I should mention that we use Apache Wicket 6.26.
update: I looked into the source of FileUploadField, and it has an explicit check on whether FileUploads is null in it's internal property, and if so returns it without checking the actual request. I don't see any way to clear this value between requests. clearInput() doesn't affect it from what I see. I'm more confused by how this is working in one page than why it's not in the one where it doesn't now. I also don't know how to make the class 'reset' between requests.
Okay, figured this out. As martin-g pointed out, the fileUploads is set null in onDetach(), which I discovered about an hour after my update. The problem is that the onDetach() first tries to null out the model object. But that method was blowing up because there was no method 'fileUploadField' on the model attached to the form which was a compound property model. The page that worked does NOT use a compound property model for the form. For some reason, when this error occurred, it was being swallowed somewhere in the call stack and did not end up in my console log.
My solution was to provide a local model to the fileUploadField since that's not how I'm interacting with the control anyway (I'm using ajax and getting the FileUpload directly each time). That fixed it. It now works everywhere.

Using iron-router with angular-meteor makes controllers being loaded twice

I have a Meteor application using angular-meteor. I need now to load different angular modules depending on url. I added iron-router to my application to do so and I continue to handle routes for each module using ngRoute and anchor nav but it behaves strangely if url contains params. I made a small test case which is available here:
https://github.com/clouchtibat/iron-router-ng-route
If you click on 'truc' link and then on 'test', next routes changes will make controller be instantiated two times. It works if urls have no params.
I also tested with ui-router (in the with-ui-router branch) and the problem is the same but in addition view is duplicated.
Is this a bug in one of the two routers or is there something wrong with my implementation?
Take a look at this conversations in the angular-meteor Github issues:
https://github.com/Urigo/angular-meteor/issues/154
https://github.com/Urigo/angular-meteor/issues/493
I think it can help you with some directions.
I am also having some hard time with mixin angular-meteor and iron:router.

Scala Lift - Robust method to protect files from hotlinking

I'm attempting to implement a way to stop hotlinking and/or un-authorised access to resources within my app.
The method I'm trying to add is something I've used before in PHP apps. Basically a session is set when the page is first called. The images are added to the page via the image tag with the session value as a parameter:
<img src="/files/image/image1.jpg?session=12345" />
When the image is requested the script checks to see if the session is set and matches the provided value. If the condition is not met the serving page returns null. Right at the end to the code I unset the session so further requests from outside the scope of the page will return null.
What would be the best implementation of this method within the lift framework?
Thanks in advance for any help, much appreciated :)
You could use a SessionVar for this purpose. In the SessionVar you’d store a Map[SessionImageId, RealImageId] and upon initialising the Session (i.e. when the page is first loaded) you’d generate some random SessionImageIds which you would map to the real image id. In your html you only expose the shadowed SessionImageId so no-one could trace back the image from the id. When the image is requested, you’d simply look up the real id in the Map.
Info: Exploring Lift, Lift wiki
Of course, if shadowing the ids is not important, you could simply use a SessionVar[Boolean].

Making GWT application crawlable by a search engine

I want to use the #! token to make my GWT application crawlable, as described here:
http://code.google.com/web/ajaxcrawling/
There is a GWT sample app available online that uses this, for example:
http://gwt.google.com/samples/Showcase/Showcase.html#!CwRadioButton
Will serve the following static webpage to the googlebot:
http://gwt.google.com/samples/Showcase/Showcase.html?_escaped_fragment_=CwRadioButton
I want my GWT app to do something similar. In short, I'd like to serve a different flavor of the page whenever the _escaped_fragment_ parameter is found in the URL.
What should I modify in order for the server to serve something else (a static page, or a page dynamically generated through a headless browser like HTML Unit)? I'm guessing it could be the web.xml file, but I'm not sure.
(Note: I thought of checking the Showcase app provided with the GWT SDK, but unfortunately it doesn't seem to support serving static files on _escaped_fragment_ and it doesn't use the #! token..)
If you want to use web.xml, then I think it won't work with a servlet-mapping, because the url-patterns ignore the get parameters. (Not 100% sure, if there is another way to make this possible.)
You could of course map Showcase.html to a servlet, and in that servlet decide what to do, based on the get parameter "_escaped_fragment_". But it's a little bit expensive to call a Servlet just to serve a static page for the majority of the requests (not too bad, but still. You could set cache headers, if you're sure that it doesn't change).
Or you could have an Apache or something in front of your server - but I understand, I wouldn't like to have to do that either. Maybe your JavaEE server (which one are you using BTW?) provides some mechanism for URL filtering before the request gets passed on to the web container - I'd like to know that, too!
Found my answer! The Showcase sample supporting crawlable hyperlinks is in the following branch:
http://code.google.com/p/google-web-toolkit/source/browse/branches/crawlability/samples/showcase/?r=7726
It defines a filter in the web.xml to redirect URLs with the _escaped_fragment_ token to the output of HTML Unit.