-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem implementing FileMiddleware #520
Comments
It looks like you are returning everything as a folder, so it never finds any files. func getAttributes(id: UUID) async throws -> CustomFileAttributes? {
// Get a file's attributes(size, date, ...) from a UUID
print(#function)
return .init(isFolder: true, size: 3, modificationDate: Date.now)
} |
Hi @adam-fowler, Thanks for the reply. Right now my issue is that this function doesn't even get called. I've added breakpoints to it and called my endpoint. At no point does it transit through this Middleware which is really weird since I've added it globally to the router ... Do you know of any reason why these function wouldn't get called? Is there any doc on how to implement them properly? Thanks again for the help. |
There is a test showing how to setup a FileProvider. Search for Though from your description of what you want to do I'm not sure why you need a custom FileProvider. The standard one used when you point the FileMiddleware at a folder returns unique ETags for every file. |
@adam-fowler I was in the understanding that the data to be served was stored externally, through a DB. |
Yeah I'm storing all my data in PostgreSQL DB. Don't know how much difference that makes? |
Ah sorry missed that bit. Yes then you'd need a FileProvider implementation. I would use the implementation from the test I pointed to you as a starting point. |
@Joannis asked for a table schema so here it goes.
This is the only thing I'm storing in my DB. A rapid disclaimer that it's called Woman cause I'm storing the personal bios and info of great women throughout history (Ada Lovelace, ...). |
What file are you trying to serve from this? |
I have a |
I get that part, but what file is being served? I don't see any files mentioned in here. Are you referring to JSON data? |
I'm still confused about what you call a I'm going to try and implement it the same way the tests do it, see what happens. |
Update I've copy/pasted the code from the test:
I also still call
I've added breakpoints to the functions and they're never called which is really weird ... I'd expect them to be called. I put a breakpoint right after the router and the middleware is added to it. Also I think this isn't going to work since the files are stored in memory which would mean that every time I restart the server it'll break the whole implementation. |
Talking with @Joannis in parallel I realise there's a bit of a misunderstanding. Current stateCurrently, when I run my server locally on my Mac and perform
I get the following result:
Expected outcomeWhat I'd want to achieve is to have a Etag header which would look something like this:
Why I need thisI'd need the Etag in order to be able to add to the "If None Match" header when performing network calls from the client. The server would then return a |
Let me get this right you want to convert a request path into a database request. The response from this request should return the contents of a database row (in JSON?), and an eTag header. If your request contains an "if none match" header it should compare this with what will be the eTag of the response and if they are the same return a NotModified response. |
That's 50% right @adam-fowler. It returns an array of DB rows/entries basically an array of Women objects. The comparison of Etags is already implemented properly in With the caveat that some of my routes like Am I making any sense? I'm a very Junior dev' so I may wildly off mark here. Is this how Etag is supposed to be used? Thanks again for the support. Much appreciated. |
There are two different reasons the FileMiddleware might not run.
Yes you are |
OK so let me see if I can get this straight. 1/ The FileMiddleware ONLY runs if a an endpoint returns a 404? 😕 Does that mean my endpoints have to return 404s for the FileMiddleware to run? I think there are several things I'm not understanding ... 2/ As described previously, all I ever do it add the Middleware to the Router in my buildApplication function. I don't add it to particular routes or endpoints since ideally I'd need this to work "globally" on all routes/endpoints ... I guess my question is what is the right way to get the FileMiddleware to run all the time ie for every incoming request? |
Yes the FileMiddleware is meant to only run if no other endpoint is matched. There is no point having the FileMiddleware return a new response if an endpoint has already generated one. The main use of the FileMiddleware is to return files that are stored on the server. The FileProvider generic parameter was added to make it a little more flexible so it could return files stored elsewhere say S3 or in a database. FileMiddleware is not used to augment already built responses. If you are only looking to provide Etag generation and comparison for your responses I would either do that in the actual endpoint or in a separate middleware. |
Am I to understand that I'd have to generate the Etag myself ? And handle the comparison myself and add the header to an |
Yes. The FileMiddleware is designed to serve files. The fact that it generates ETag's is a very small part of it and linked to the fact that it is serving files. |
OK so I think this is on me. I wrongly understood that I could generate Etags. Legally speaking how allowed am I to use your implementation to add my Etags to my headers? I wouldn't want to steal your IP. |
I'm happy for you to copy it with attribution |
🆗 thanks so much. I think we've solved the issue in the sense that I thought that Thank you so very much for your time and effort in trying to help me understand what's what. Goes a long way and means a lot. I hope you have a great day and will 1000% share any progress I make on implementing it myself. Should I let you close the ticket or would you like me to do it? |
Also and keeping in mind I'm a very Junior Dev' with little actual experience I was wondering wether you'd be interested if I opened a pull request on this repository to add my implementation to the official I recognise that it's going to be super hard but I'd like to try. |
How you generate an ETag is dependent on situation and source of your data. Some people think it should be the md5 of the file contents, some people think it should a combination of file modification data, size and inode. In the FileMiddleware I went for file modification data and size. If you can come up with some generic solution I'm happy to have a look |
I've begun implementing my Reusing the I was thinking of using the date the last element of the array was modified as a date. Does this seem smart to you? |
@Bamakoo I think you should do what works for your project first. Then we can discuss whether it'll be suitable for Hummingbird. |
👋
My name is Emma and I'm an iOS Developer with a keen interest in Server Side Swift development with some Vapor personal projects under my belt. Blown away by what you've done with Hummingbird. Love it.
I'm currently attempting to use the ETag in order to perform some client-side caching with Swift Data for a personal project that I'm working on. Running into some issues getting it to work.
What I've attempted
So far, I've attempted adding ...
... to my
buildApplication
function to no avail.This is what a WIP version of
FileProviderManager
looks like:What's weird is that I've added breakpoints to these function and they're never called, ran my server, called an endpoint ...
I've tried a workaround which I don't like which would entail me adding it to specific routes - keep in mind that ideally I'd like to have the Etag on all my objects -.
This hasn't worked either 🙃
I'm at my wits end and would love some help. I reached out to @Joannis who was kind enough to try to set me on the right path. He mentioned some documentation, specifically for
ResponseBody
I've checked it out and can't see how that'd help me. There's no mention of Etag.He also mentioned that there were some sample projects available but I've had a look at most of the projects and I haven't found a single one that had a working implementation of a
FileManager
instance.I'd really appreciate it if someone could walk me through where I'm going wrong. I've also added comments on what the role of every function was, feel free to correct me if I'm wrong.
Thank you so much for your time and patience.
CC @adam-fowler
The text was updated successfully, but these errors were encountered: