Fork me on GitHub
#biff
<
2023-07-29
>
Sasha V. Bogdanov17:07:13

Hello! Is it possible to start two different routers? One for VPN address (e.g. 10.8.0.1), and second for public IP.

Jacob O'Bryant17:07:44

I'm sure it's doable 🙂. The first step would be to make sure that http requests sent to both addresses make it to the Biff app/jetty. I'm not sure if that'll work out of the box or if you'd need to add some more nginx configuration (e.g. perhaps create https://github.com/jacobobryant/biff/blob/master/example/server-setup.sh#L94-L115?) Once that's in working, you could then duplicate this bit of code: https://github.com/jacobobryant/biff/blob/master/example/src/com/example.clj#L22-L28 e.g. instead of a single handler fn, you'd want to do something like this:

(def public-routes [["" {:middleware [biff/wrap-site-defaults]}
                     (keep :routes plugins)]
                    ["" {:middleware [biff/wrap-api-defaults]}
                     (keep :api-routes plugins)]])

(def internal-routes [["" {:middleware [biff/wrap-site-defaults]}
                       (keep :internal-routes plugins)]])

(def public-handler (-> (biff/reitit-handler {:routes public-routes})
                        biff/wrap-base-defaults))

(def internal-handler (-> (biff/reitit-handler {:routes internal-routes})
                          biff/wrap-base-defaults))

(defn handler [ctx]
  ((if (internal-request? ctx)
     internal-handler
     public-handler)
   ctx))

Jacob O'Bryant17:07:42

It looks like Biff's default nginx configuration sets a Host header before proxying the request to Biff, so the internal-request? function could probably look at that header.

Jacob O'Bryant17:07:50

I'm sure there are other ways it could be done as well. e.g. if you wanted to use a single reitit router, perhaps have nginx prepend an /internal/ to URLs depending on the host, and then just add that to your reitit routes instead of making a second handler.

Sasha V. Bogdanov05:07:27

I tried approach with middleware like this:

(def plugin
  {:routes [["/" {:middleware [mid/restrict-public]}
             ["" {:get home-page}]
             ["edit-user" {:post edit-user}]]
            ["/action" {:get action}]
            ["/info" {:get info}]
            ["/error" {:get error}]]})
and
(defn restrict-public [handler]
  (fn [ctx]
    (if (or (= (:server-name ctx) "10.8.0.1")
            (= (:server-name ctx) "127.0.0.1")
            (= (:server-name ctx) "localhost"))
      (handler ctx)
      {:status 403})))
Looks like it could work. Isn't it?

Sasha V. Bogdanov06:07:13

But I can't understand why

{:status 303
  :headers {"location" "/"}}
is doing what we need, but
{:status 403}
or
{:status 200
 :body "<h3>Action performed</h3>"}
cause only javascript console message and downloading of plain text file with :body contents?

Jacob O'Bryant16:07:11

For this:

(defn restrict-public [handler]
  (fn [ctx]
    (if (or (= (:server-name ctx) "10.8.0.1")
            (= (:server-name ctx) "127.0.0.1")
            (= (:server-name ctx) "localhost"))
      (handler ctx)
      {:status 403})))
The only thing that comes to mind is that in production, Biff uses nginx to proxy requests to the clojure app, so biff is receiving requests on localhost. My guess is that :server-name will thus always be localhost. However if you check (:headers ctx) instead, there should be a Host header or something that has the original host. Re: these: >
{:status 403}
> or >
{:status 200
>  :body "<h3>Action performed</h3>"}
I think you need to add content-type? like
{:status 403
 :headers {"content-type" "text/plain"}
 :body ""}

{:status 200
 :headers {"content-type" "text/html"}
 :body "<h3>Action performed</h3>"}

Jacob O'Bryant16:07:50

(As a shortcut, with Biff's default middleware, if you return a vector, e.g. [:h3 "Action performed"], then it'll get expanded to {:status 200 :headers {"content-type" "text/html"} :body "<h3>Action performed</h3>"})

👍 2
Jacob O'Bryant18:07:28

FYI! There's a bit of Biff roadmap stuff in here. Also shout out to #available-for-jobs which is how I got my new role. https://tfos.co/p/i-got-a-job/

12
2
👍 2
Epidiah Ravachol19:07:00

Congratulations!

sergey.shvets20:07:59

Congratulations! We've been lucky you had time to build biff 🙂

🙌 2
🎅 2
OliverM19:07:11

Hi! I've been working through the tutorial for Biff, thank you so much for all the work you've put into it! It's been going well so far, but I'm getting the following error when I try to run bb deploy:

! [rejected]        main -> master (non-fast-forward)
error: failed to push some refs to ''
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
I can run git push prod main:master with no errors so I'm not sure what to do here. I've updated my secrets.env file which I presume is pushed to the remote by bb deploy , which would explain some of the issues I'm seeing despite trying bb refresh after doing the git push.

Jacob O'Bryant20:07:08

if git push prod main:master works manually, then I'm guessing bb deploy is running a different command. What does your :tasks section in config.edn look like?

Jacob O'Bryant20:07:27

(Also you're welcome, glad you've been enjoying the tutorial!)

OliverM21:07:18

Thanks @U7YNGKDHA! The :tasks section reads:

{;; Set this if the auto-detection doesn't work. See
         ;; 
         ;; for possible values (for example: "tailwindcss-macos-arm64").
         :biff.tasks/tailwind-file nil
         :biff.tasks/clj-args ["-J-XX:-OmitStackTraceInFastThrow"
                               "-J-XX:+CrashOnOutOfMemoryError"
                               "-J-Xss2m"
                               "-J-Duser.timezone=UTC"
                               "-M" "-m" "com.biffweb.examples.electric"
                               "--port" "7888"
                               "--middleware" "[cider.nrepl/cider-middleware,refactor-nrepl.middleware/wrap-refactor]"]
         :biff.tasks/on-soft-deploy "\"(com.biffweb.examples.electric/on-save @com.biffweb.examples.electric/system)\""
         ;; Replace "master" with e.g. "main:master" or "dev:master" if you
         ;; want to deploy a different branch, for example:
         ;:biff.tasks/deploy-cmd ["git" "push" "prod" "main:master"]
         :biff.tasks/deploy-cmd ["git" "push" "prod" "main:master"]
         :biff.tasks/server "***.*****.com"}
(I'm using the electric integration you published recently)

Jacob O'Bryant22:07:03

hm, well that looks correct. it should just be running a plain git push prod main:master. maybe try making a new commit, run git push prod main:master, make another commit, then run bb deploy? just to double check that you're still getting an error from one but not the other

OliverM12:07:07

No change unfortunately. I don't know that I've actually managed to run bb deploy successfully after the first time deployment :thinking_face:

ianjones14:07:08

I ran into this and just added “-f” to the :biff/tasks/deploy-cmd and it seemed to work

ianjones14:07:12

obviously not idea to force push but you gotta do what you gotta do 😛

Jacob O'Bryant16:07:58

> I ran into this and just added “-f” to the :biff/tasks/deploy-cmd and it seemed to work Yeah, that would fix it 🙂 . That might be the best approach now anyway since I'm pretty stumped... I would like to figure out what the root cause is, especially if it's happening for multiple people. I'm just super confused about how git push prod main:master works but bb deploy doesn't. You're running them both from the same directory, right? At this point I would just start bisecting the code: copy https://github.com/jacobobryant/biff/blob/master/tasks/src/com/biffweb/tasks.clj#L188 into your tasks.clj file (and change the @config to @tasks/config), then edit bb.edn and change com.biffweb.tasks/deploy to <your project namespace>.tasks/deploy, and then start adding some prns. e.g. right before the (if deploy-cmd ...) bit, throw in a (prn deploy-cmd). oh, you'll also need to add [babashka.tasks :refer [shell]] to your requires in tasks.clj

OliverM18:07:14

I just get ["git" "push" "prod" "main:master"] from that suggested (prn deploy-cmd) . And the same inside the following (if ...) clause. I did a manual -f push following @U0CKDV6DB suggestion and now my bb deploy commands work without needing a -f to be added. Is it something git-specific? I ran both in the same directory (the project root). Given that bb deploy now runs without complaint after a single git push prod main:master -f I don't know where else to look...

ianjones19:07:35

I ran into the same thing and also took -f off after I did it the one time

ianjones19:07:01

Im guessing theres some sort of subtle issue with main:master thinking-face

👍 2
Jacob O'Bryant00:08:02

very interesting does seem likely to be main:master related; maybe I can reproduce it sometime with that. I'm still baffled about how git push prod main:master works; hopefully I can reproduce the bug and then I'll do some more investigatin'. Issue here: https://github.com/jacobobryant/biff/issues/164. In any case, there's no harm to using -f, so that's fine as a workaround.

👍 2
Sasha V. Bogdanov06:07:13

But I can't understand why

{:status 303
  :headers {"location" "/"}}
is doing what we need, but
{:status 403}
or
{:status 200
 :body "<h3>Action performed</h3>"}
cause only javascript console message and downloading of plain text file with :body contents?