The BEST way to proxy your API in Nuxt

Sdílet
Vložit

Komentáře • 153

  • @TheAlexLichter
    @TheAlexLichter  Před 8 měsíci +3

    Which strategy did you use so far? Any plans to switch now? 🙊

    • @moosesaid
      @moosesaid Před 8 měsíci +1

      Hey Alex, great work on your videos! Like your explanations so much
      But I guess there is another way to do this from Nuxt modules, right? Access `useRuntimeConfig()` from there and tweak routeRules.

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      Hey Mostafa! Thanks 🙏🏻
      Interesting idea. I think it might but haven’t tried it yet. Will report back when I did! 👌🏻

    • @djpunisha29
      @djpunisha29 Před 3 měsíci

      funny, no strategy works on my project :|
      any chance of reaching out to you? google meet call?

    • @AnthonyRuelle
      @AnthonyRuelle Před měsícem

      For my part, for the new application that I am developing and which will have high traffic, I opted for a BFF (Back for front)
      Each endpoint I call is wrapped at my server/routes/ ...
      This allows me to hide the endpoint of the called API but also and above all to hide the parameters passed such as the app token (or the connected user)
      what do you think of this? :)

    • @TheAlexLichter
      @TheAlexLichter  Před měsícem

      @djpunisha29 sorry, missed that comment! Hit me up on discord or book a call through my website ☺️

  • @ammarmughal91
    @ammarmughal91 Před 8 měsíci +7

    I wish i was taught everything by you it would have saved me a lot of time. Great video!

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      Thank you 🙏🏻
      No worries, more content is in the making 😊
      Is there anything specific that you want to learn about?

  • @TheLoGgIDK
    @TheLoGgIDK Před 8 měsíci +2

    I needed this video a month ago, but nice to see that it is finely here . ^_^

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      That’s unfortunate 🙈
      Anything you are stumped about right now though?

  • @RIT_Edition
    @RIT_Edition Před 8 měsíci +8

    Please create a video to protect the server API endpoint from direct calls from other websites. Eg - Allow access to certain domains, and cors, add authentication and more security feature

  • @laurencebarnes1322
    @laurencebarnes1322 Před 7 měsíci

    Thank you for helping us understand why the other options didn't work, and how / why nitro work. I must admit I forgot to include the `server: true` prop in the $fetch options, and when testing the production version, the proxy wasn't working. Thankfully I realised my mistake and now everything is working smoothly finally!

    • @TheAlexLichter
      @TheAlexLichter  Před 7 měsíci +2

      You are very welcome! Yeah, I only mentioned the "server: true" part (it is the default though) for useFetch, so that's a tiny bit on me. Glad it worked though 🙏

  • @chstappert
    @chstappert Před 8 měsíci +1

    This is very important and a pretty good idea ;-). Looking forward to implement!

  • @timostolz
    @timostolz Před 5 měsíci +2

    Thank you very much, this helps me a lot. Still, I need to know how to proxy websockets.

  • @linpengteng
    @linpengteng Před měsícem

    Using `~/server/api/[...]` is indeed quite concise and effective. I have another question. If `~/server/middleware/api.ts` is used, can it also solve the problems related to server-side interface acquisition and runtime environment variable configuration? Regarding server-side middleware, I don't quite understand when it is needed?

  • @andreygaisinskii111
    @andreygaisinskii111 Před 9 dny

    Thank you for the video, very interesting! Im using a wrapper around useFetch and with this wrapper [...].ts aka catch all guard doesnt seem to work. I've removed the wrapper (used plain useFetch) and it worked! Is it possible to make it work with a wrapper? The only reason i use the wrapper is because i need to pass baseURL and some headers. I used official method for creating the wrapper if it matters, the one that is on nuxt site.

  • @Agboihip
    @Agboihip Před 8 měsíci +3

    Nice work, thanks.
    So far I call external api directly. But with your proxy approach now, how to deal with the authorisation, to serve the api token as the same time securing routers with middleware ? Do I use both server and application middlewares, bearer token saved in pinia’s store.

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      Thanks 🙏🏻
      Yes, you'd call e.g. a `/api/XYZ` endpoint which is the shown Nitro proxy endpoint and ensure that the headers (e.g. for auth) are present in that call. `proxyRequest` will forward all headers automatically (except some ignored ones. - github.com/unjs/h3/blob/53703dc860f1ff6fe7ce71d543deff1cfa810b11/src/utils/proxy.ts#L24-L31)!

  • @bratiche
    @bratiche Před 8 měsíci +3

    Great video! i just have one question, what would be the advantages of proxying our requests vs calling the api directly?

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +3

      Avoid CORS and „hide“ the backend urls.
      Also load balancing and co if you have multiple URLs

    • @RockGonzo17
      @RockGonzo17 Před 7 měsíci

      I've also added some more use cases in my comment if you want to check it out. :)

  • @dexterstm
    @dexterstm Před 8 měsíci +4

    Another great video Alex, just a question, if I'm proxying my request to an external backend endpoint and I'm required to pass a Authorization Header. How should I go about implementing this? , will proxyRequest forwards the headers as well?

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      Yes, it will! Compared to another helper called `sendProxy`, `proxyRequest` will merge the request headers for us. This happens here in the code: github.com/unjs/h3/blob/53703dc860f1ff6fe7ce71d543deff1cfa810b11/src/utils/proxy.ts#L54-L70

    • @dexterstm
      @dexterstm Před 8 měsíci

      @@TheAlexLichter Nice! another question, how would i set the Authorization Bearer Header?
      I tried using the setHeader helper but it didn't work.
      setHeader(event, 'Authorization', 'Bearer )

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      I think you can set it through the 3rd parameter of proxyRequest via { headers: { Authorization: ‘token here' } }

  • @oyedeji.oyewole
    @oyedeji.oyewole Před 8 měsíci +2

    Please can you explain what island components are, why and if we should use them?

  • @Tarabass
    @Tarabass Před 8 měsíci +1

    Nice! Thx :)
    Offtipc; What I still hate about routerules is that headers are set only for response headers.

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      You are welcome!
      I think that is a good candidate for a feature request issue 😁

    • @Tarabass
      @Tarabass Před 8 měsíci +1

      ​@@TheAlexLichter
      Again? I see a pattern lol 😅
      Will do, NP. Tomorrow 🎉

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      @Tarabass good ideas = good issues I’d say 😁

    • @Tarabass
      @Tarabass Před 8 měsíci +1

      @@TheAlexLichter Issue #24971 opened

  • @SKOTSKOT
    @SKOTSKOT Před měsícem

    Great video. could i also do this to proxy websocket endpoint ?

  • @honzamrazek8581
    @honzamrazek8581 Před 5 měsíci

    Thank you for your content Alex, it is most helpful with my Bachelor thesis.💪

    • @TheAlexLichter
      @TheAlexLichter  Před 4 měsíci +2

      Glad to help! What are you writing about (also just finished my "master-equivalent" thesis)?

    • @honzamrazek8581
      @honzamrazek8581 Před 4 měsíci

      @@TheAlexLichter I am rewriting a section in one of the systems we use at school. It serves as a portal for submitting team projects that are divided into iterations. We are currently migrating from Django to .NET Core backend and Nuxt on frontend.
      I have to say that comming from Next.js, the DX of Nuxt combined with Nuxt UI is something else. It is amazing and I am very glad we chose this tech stack. It has an amazing community.
      What was your thesis about?

  • @user-qb7yc3qg3b
    @user-qb7yc3qg3b Před měsícem

    what i can do if i have custom $fetch plugin, with base api url, JWT tokens, but i want to proxy it through nitro for some security reasons and send user-agent and ip to api?

  • @ericpodhorecki3593
    @ericpodhorecki3593 Před měsícem

    Will these techniques pass along any cookies that exist for the /api url ? If you have /api/login proxied to another api that actually handle the login. How will cookies be ahndled ? Cookies are super important but nobody seem to explain how to handle them !

  • @oiluis
    @oiluis Před 3 měsíci

    Hey Alex! Great stuff as usual! Let me know if I am overthinking, but after reading all comments I didn’t see any mentions on performance. Let’s suppose I have a backend API on another server / port written on another language / framework than ts & nuxt … if I understood your approach correctly after implementing it on my app you just added a simple proxy that forwards the request to “maybe” another proxy or whatsoever … wouldn’t be faster / easier to just create a custom fetch wrapper that uses nuxt config to point to the “right” proxy? For me the proposed approach seems to be another layer / bottleneck that can potentially generate errors or who knows what in a scenario of high volume of transactions… am I missing something here?

    • @TheAlexLichter
      @TheAlexLichter  Před 3 měsíci

      Hey Luis! Thanks for the comment.
      Perf-wise, the overhead should be rather small + you *can* also apply route rules or custom caching to it to even improve performance! A good example @ x.com/Atinux/status/1798294901559546038
      But if you don't need the proxy (no caching wanted, no CORS issues etc. etc.) you are free to not proxy at all 👌

    • @oiluis
      @oiluis Před 3 měsíci

      @@TheAlexLichter thank you for your prompt response … when you say
      “You are free to not proxy at all”
      This means that having a useCustomFetch with baseapi + headers rewrite seems to be a good option?

    • @TheAlexLichter
      @TheAlexLichter  Před 3 měsíci

      Sure, you can hit the API directly + set the headers you need, absolutely

  • @olatunjiolakunle6908
    @olatunjiolakunle6908 Před 8 měsíci +1

    Another good video. Thanks Alex.

  • @oleggerasymeko676
    @oleggerasymeko676 Před 4 měsíci +1

    oh, wow. This is really helpful.

  • @Thr0nSK
    @Thr0nSK Před 8 měsíci +2

    What are the performance implications of using nuxt proxying, as opposed to calling the external backend endpoints directly?

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      Should be a rather small overhead, especially because you commonly have to deal with CORS otherwise 👌🏻

    • @RIT_Edition
      @RIT_Edition Před 8 měsíci

      @@TheAlexLichter What if someone our proxied URL from different domain?

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      You mean what if someone accesses that URL from another project?
      Well, then you could eg blacklist the IP (or domain)

    • @RIT_Edition
      @RIT_Edition Před 8 měsíci

      @@TheAlexLichter Instead of blacklisting how to allow access to certain domains or IP

  • @gihandilanka
    @gihandilanka Před měsícem +1

    Thanks for the video, getting this 502 error
    at createError (./node_modules/h3/dist/index.mjs:78:15)at sendProxy (./node_modules/h3/dist/index.mjs:1168:11)at process.processTicksAndRejections (node:internal/process/task_queues:95:5)at async ./node_modules/h3/dist/index.mjs:1975:19at async Object.callAsync (./node_modules/unctx/dist/index.mjs:72:16)at async Server.toNodeHandle (./node_modules/h3/dist/index.mjs:2266:7)

    • @TheAlexLichter
      @TheAlexLichter  Před měsícem

      Are you sure that the API to proxy to is available?

  • @FrontendDays
    @FrontendDays Před 8 měsíci +1

    Thanks for the solution! You helped me a lot

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      Glad to hear that! You are welcome ☺️🙌🏻

  • @silvesterwali6565
    @silvesterwali6565 Před 8 měsíci

    Thank you for the great videos. Can you make a video on how to handle the auth with a proxy...

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      I’ll add it to the list! Anything to cover specifically with regards to proxy and auth?

    • @silvesterwali6565
      @silvesterwali6565 Před 8 měsíci

      @@TheAlexLichter maybe you have an idea how proxy handle token to passing every request.so on the frontend useFetch and $fetch will be clean. I'm using Laravel as an API. So far i end up using composable to manually handle authentication in every request like redirect ..get the token from cookies..and i think this is verbose . It will help if you have an idea for this

  • @arnaudkinnoudo3351
    @arnaudkinnoudo3351 Před 3 měsíci

    Thank you for this great content.
    Please I remark that proxyRequest doesn't handle well the 422 errors from an external api. It returns 200 status code. Is there a way to handle that ?

    • @TheAlexLichter
      @TheAlexLichter  Před 3 měsíci +1

      That sounds like a bug! Can you reproduce that and raise an issue in the h3 repo?

  • @hamedfaryabi1030
    @hamedfaryabi1030 Před 8 měsíci +1

    Perfect solution! Thanks

  • @Tarabass
    @Tarabass Před 8 měsíci +1

    @TheAlexLichter
    What about putting the endpoint not in the `api` folder but instead put it in the `routes` folder? In that way there's no need for replacing 'api'.
    For me it's very unclear what the routes folder is all about. In some video's it's used to return html, strings and stuff.

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      Would also work! I’ll make a video about that 🙊

    • @Tarabass
      @Tarabass Před 8 měsíci

      @@TheAlexLichter you're the best!

  • @dennismaa1103
    @dennismaa1103 Před 5 měsíci

    Hey Alex, thanks for the really informative and well explained video. I have one more question though, how would you handle the case where I only want to have this proxy during development. So I only use it to handle cors and cookie issues, but I don't need/want to have this proxy in production stage because that would mean an additional, unnecessary load on the server.

    • @TheAlexLichter
      @TheAlexLichter  Před 4 měsíci

      Use the env aware config - czcams.com/video/DFZI2iVCrNc/video.html

  • @CharlesCurrierR
    @CharlesCurrierR Před 8 měsíci +1

    What approach would you recommend for transforming the data received from the proxy. I tried saving the result of proxyRequest to a local variable, and returning something else but the data I get from the API route is always the data from proxyRequest.

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      In this case you might consider using $fetch explicitly and transform the data afterwards 😊

  • @youhan96
    @youhan96 Před 4 měsíci

    Thanks Alex. I used the routeRules proxy on my project couple month ago. I have a env variable on Vercel which is set to different URL for prod and preview, and routeRule proxy uses that. Do you suggest using runtimeConfig method for that?

    • @TheAlexLichter
      @TheAlexLichter  Před 4 měsíci

      Yes, absolutely! RuntimeConfig is the best option here 👌🏻

  • @schwangtv7448
    @schwangtv7448 Před 10 dny +1

    It doesn't work with npm run generate. We are doing a client side only nuxt app that is statically generated. Everything works great but changing the base url etc of our api calls doesn't work! it works great when doing npm run dev or npm run build. However, we have specific requirements that make us deploy on IIS and we aren't allowed to use the node plugin... So static site generation is our only option.
    Our app use to use Axios as a plugin, and it was dead simple to modify the configuration so that each api call hit a specific base url etc... Now with nuxt and $fetch there is always an edge case that doesn't work.
    So in other words: Does using nitro directory with the server directory work client side? YES, but does it work client side when you generate the project instead of build? NO.

    • @TheAlexLichter
      @TheAlexLichter  Před 10 dny

      That is correct. If you statically generate your site, there is no server serving which means nothing can be proxied.
      Also touched on that in czcams.com/video/Fp04Kw4nBE8/video.html

    • @schwangtv7448
      @schwangtv7448 Před 10 dny

      ​@@TheAlexLichterI appreciate the response. Is there a solution that I can use to change the base URL for all of the $fetch calls? If I were using axios which we were originally, then I can simply change that as the base configuration and it's pretty easy... Is there something similar I can do? We are SSR: false and using generate, and so I respectfully ask you to consider adding a feature so I can configure the base URL for my requests.

    • @TheAlexLichter
      @TheAlexLichter  Před 10 dny

      @schwangtv7448 oh you can for sure. You just have to rebuild the app when you change it.
      An easy way would be, similar to axios, using $fetch.create and pass the base url there. Then, use the newly created fetch instance everywhere

    • @TheAlexLichter
      @TheAlexLichter  Před 10 dny

      See also czcams.com/video/jXH8Tr-exhI/video.html

  • @sushant_
    @sushant_ Před měsícem

    Dont know why its not working in my case, I am using server/routes/[...].ts as my apis doesnt begin with api. It will also work in the same way right?

    • @TheAlexLichter
      @TheAlexLichter  Před 10 dny

      that's a catch-all server route then, yes. Happy to look into a stackblitz or repo.

  • @adrianpdm
    @adrianpdm Před 4 měsíci

    in a deployment platform like Railway, where cpu and egress is billed, wouldnt this result in unnecessary cost?

    • @TheAlexLichter
      @TheAlexLichter  Před 4 měsíci

      It’d be count into bandwidth, yes. CPU minimally, that should be negligible.

  • @tomasprieto9746
    @tomasprieto9746 Před 8 měsíci +1

    Great clip

  • @fabricec2074
    @fabricec2074 Před 8 měsíci +2

    Could you have used $fetch instead of proxyRequest ?

    • @olatunjiolakunle6908
      @olatunjiolakunle6908 Před 8 měsíci +1

      Yes, just add the target as the path, proxyRequest is just help function provided by h3

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +2

      Would work (as commented before)! But proxyRequest passes all the headers and body of the incoming request, which is often desired
      with $fetch it is more like a BFF pattern (fetch + maybe transform the data)

  • @thibaultfae5589
    @thibaultfae5589 Před 3 měsíci

    Thanks a lot for your video, helped me a lot but I have an issue for the past days: data are now received in binary instead of plain JSON text. Specifying the encoding helped me but I don't think this is the correct approach, any ideas ?

    • @TheAlexLichter
      @TheAlexLichter  Před 3 měsíci

      Does the API set the correct „content-type“ header?

    • @thibaultfae5589
      @thibaultfae5589 Před 3 měsíci

      @@TheAlexLichter thanks for your answer, it is a 3rd-party api: content-type is set to application/json
      thanks

    • @TheAlexLichter
      @TheAlexLichter  Před 3 měsíci

      And does the fetch call sets a different `Accept` by any chance? Worst case, you can use $fetch to ensure the responseType will be json ☺️

    • @thibaultfae5589
      @thibaultfae5589 Před 3 měsíci

      @@TheAlexLichter I will check it out, thanks a lot pal

  • @Mikhail_Kominov
    @Mikhail_Kominov Před 8 měsíci +1

    Alexander, will there be a video about caching nitro?

  • @nested9301
    @nested9301 Před 8 měsíci +1

    can you talk about swr in nuxt thank you great video!

  • @sania3631
    @sania3631 Před 8 měsíci +1

    Great video... thanks! I am wondering if it is possible to implement it with Apollo graphql.

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      Yes, absolutely. I wouldn't see why not 😊

    • @sania3631
      @sania3631 Před 8 měsíci

      @@TheAlexLichter I am using Apollo inside the Pinia store. Am I supposed to run it on the proxied server?

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      @sania3631 not sure I understand. When you use Apollo, do you need a store then?
      Probably Nuxt GQL client would be a bit more lightweight. Then, use the path you wanna proxy as endpoint

    • @RockGonzo17
      @RockGonzo17 Před 7 měsíci +1

      If you want to proxy requests to a GraphQL backend, that definitely works. You basically create the proxy and tell your Apollo client that the httpEndpoint is your proxy (instead of the URL to the actual GraphQL backend). I did that in a project and that works just fine.

  • @umbrellacoro9953
    @umbrellacoro9953 Před 2 měsíci

    Hi Alex! Thank you for the video. I have a question. When I built a Nuxt 3 app, your strategy 4 did not work with $fetch. It did not replace the API URL. Do you have any suggestions on how to resolve this?

    • @TheAlexLichter
      @TheAlexLichter  Před 2 měsíci

      How do you mean "it did not replace the API URL"? 🤔

    • @umbrellacoro9953
      @umbrellacoro9953 Před 2 měsíci

      "When I make a request, it doesn't replace myProxyUrl with 'xx.xx.xx.xx' in nuxt.config.ts."

    • @umbrellacoro9953
      @umbrellacoro9953 Před 2 měsíci

      @@TheAlexLichter "When I make a request, it doesn't replace myProxyUrl with in nuxt.config.ts."

    • @umbrellacoro9953
      @umbrellacoro9953 Před 2 měsíci

      When I make a request, it doesn't replace myProxyUrl with in nuxt.config

    • @TheAlexLichter
      @TheAlexLichter  Před 23 dny

      Do you have some kind of reproduction for that?

  • @TheVlads
    @TheVlads Před 7 měsíci

    thank you for the explanation.. but how if we have more than one proxy base url? thank you

    • @TheAlexLichter
      @TheAlexLichter  Před 7 měsíci

      No problem! Then add them both via runtimeConfig and choose the "correct one" based on your criteria, e.g. the URL path

  • @saidinusah
    @saidinusah Před 5 měsíci

    Hi, does the work in production mode? I tried the vite server approach last week but it didn't work in production. I proxied the API was due to an SSL certificate validation error.

    • @TheAlexLichter
      @TheAlexLichter  Před 5 měsíci

      Yes, the two shown techniques at the end work in prod :)

  • @conan_fans
    @conan_fans Před 4 měsíci

    right on ❤‍🔥

  • @bruno.pbarbosa
    @bruno.pbarbosa Před 6 měsíci

    Do you have any special recomendations if we're trying to proxy images and need to pass on auth headers? had this working on a nuxt 2 project but struggling to figure out how to get it going in nuxt 3

    • @TheAlexLichter
      @TheAlexLichter  Před 6 měsíci +1

      Should work the same way (with a nitro endpoint serving them). If not, hit me up with a "broken" example reproduction :)

    • @bruno.pbarbosa
      @bruno.pbarbosa Před 6 měsíci +1

      @@TheAlexLichter Thanks! Managed to get it working, but had to do it differently - added a file to the /server/middleware/ folder, and here it worked (my endpoint isn't called api, so caused some issues figuring why it didn't work). Might be worth noting in case others struggle with the same case :)

  • @Code2Master
    @Code2Master Před 8 měsíci +1

    thanks man

  • @jingwang-0811
    @jingwang-0811 Před 8 měsíci

    very nice!!

  • @NamNam2412
    @NamNam2412 Před 7 měsíci

    it's good for GET request, how about other methods like POST, PUT, DELETE? I've tried, but it's responsed with status 405 METHOD NOT ALLOWED :(

    • @TheAlexLichter
      @TheAlexLichter  Před 7 měsíci

      Should also work when not using .get.ts as suffix ☺️

    • @NamNam2412
      @NamNam2412 Před 7 měsíci

      @@TheAlexLichter I'm not using .get.ts, just [...] .ts like your video :(

    • @NamNam2412
      @NamNam2412 Před 7 měsíci +1

      @@TheAlexLichter oh, my bad, that error is because of my BE response, not because of the proxy, thanks :D

  • @Vladimir-if1uk
    @Vladimir-if1uk Před 6 měsíci

    Can we use Nginx to proxy? Is it better? what are the pros and cons

    • @TheAlexLichter
      @TheAlexLichter  Před 5 měsíci

      Sure, you can use NGINX for proxying! "Better" depends on your need. A simple API proxy should not make a big difference perf-wise but lots of rules could make a difference. Be aware that you still need to set up your dev proxy differently then (e.g. via Nuxt) ☺️

  • @wailantirajoh3052
    @wailantirajoh3052 Před 8 měsíci

    Somehow the [...].ts doesnt work on production build. only works on development mode

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci

      How and where do you deploy? 🤔

    • @wailantirajoh3052
      @wailantirajoh3052 Před 8 měsíci

      @@TheAlexLichter trying on local using pnpm build and then run `node .output/server/index.mjs`

    • @wailantirajoh3052
      @wailantirajoh3052 Před 8 měsíci +1

      @@TheAlexLichter ill try to create minimal reprod latter and submit to nuxt issues i think

    • @wailantirajoh3052
      @wailantirajoh3052 Před 8 měsíci +1

      Nevermind, while creating reproduction. it work as expected, let me check my code 🤧

    • @TheAlexLichter
      @TheAlexLichter  Před 8 měsíci +1

      That's the best part of reproductions IMO! Happens to me so often 😋