hoophq / sequence

Immutable, scalable, and easy to use ledger service.
Apache License 2.0
494 stars 31 forks source link

Internal server error: exception #17

Open lgrkvst opened 4 years ago

lgrkvst commented 4 years ago

Hi, I'm playing around with Sequence and bumped into trouble early on:

docker-compose up

Starting sequence_dynamodb_1 ... done
Creating sequence_sequence_1 ... done

curl http://localhost:8910/v1/transactions \ -H 'Authorization: Basic MjyNj0Mwo=' \ -d '{ "from": "abc", "to": "Alice", "amount": 1000, "currency": "usd" }'

Internal server error: exception

The Sequence console reports the following:

sequence_1  | INFO  io.pedestal.http  - {:msg "POST /v1/transactions", :line 80}
sequence_1  | INFO  io.pedestal.http.cors  - {:msg "cors request processing", :origin nil, :allowed nil, :line 84}
sequence_1  | ERROR i.p.http.impl.servlet-interceptor  - {:msg "error-ring-response triggered", :context {:io.pedestal.interceptor.chain/stack (#Interceptor{:name :io.pedestal.http.impl.servlet-interceptor/stylobate} #Interceptor{:name :io.pedestal.http.impl.servlet-interceptor/terminator-injector}), :request {:protocol "HTTP/1.1", :async-supported? true, :remote-addr "172.19.0.1", :servlet-response #object[org.eclipse.jetty.server.Response 0x5b15bdac "HTTP/1.1 200 \nDate: Fri, 18 Sep 2020 14:58:38 GMT\r\n\r\n"], :servlet #object[io.pedestal.http.servlet.FnServlet 0x718000a1 "io.pedestal.http.servlet.FnServlet@718000a1"], :headers {"user-agent" "curl/7.64.1", "authorization" "Basic MjyNj0Mwo=", "host" "localhost:8910", "accept" "*/*", "content-length" "73", "content-type" "application/x-www-form-urlencoded"}, :server-port 8910, :servlet-request #object[org.eclipse.jetty.server.Request 0x71f2f53b "Request(POST //localhost:8910/v1/transactions)@71f2f53b"], :content-length 73, :content-type "application/x-www-form-urlencoded", :path-info "/v1/transactions", :url-for #object[clojure.lang.Delay 0x13737d55 {:status :pending, :val nil}], :uri "/v1/transactions", :server-name "localhost", :query-string nil, :path-params {}, :body #object[org.eclipse.jetty.server.HttpInputOverHTTP 0x2462d585 "HttpInputOverHTTP@2462d585[c=0,q=0,[0]=null,s=STREAM]"], :scheme :http, :request-method :post, :context-path ""}, :bindings {#'io.pedestal.http.route/*url-for* #object[clojure.lang.Delay 0x13737d55 {:status :pending, :val nil}]}, :enter-async [#object[io.pedestal.http.impl.servlet_interceptor$start_servlet_async 0x1b651f9c "io.pedestal.http.impl.servlet_interceptor$start_servlet_async@1b651f9c"]], :io.pedestal.interceptor.chain/terminators (#object[io.pedestal.http.impl.servlet_interceptor$terminator_inject$fn__13520 0x526ce478 "io.pedestal.http.impl.servlet_interceptor$terminator_inject$fn__13520@526ce478"]), :servlet-response #object[org.eclipse.jetty.server.Response 0x5b15bdac "HTTP/1.1 200 \nDate: Fri, 18 Sep 2020 14:58:38 GMT\r\n\r\n"], :route {:path "/v1/transactions", :method :post, :path-re #"/\Qv1\E/\Qtransactions\E", :path-parts ["v1" "transactions"], :interceptors [#Interceptor{:name :io.pedestal.http/json-body} #Interceptor{:name :auth} #Interceptor{:name :parse-tx} #Interceptor{:name :spec-tx} #Interceptor{:name :from-balance} #Interceptor{:name :genesis-balance} #Interceptor{:name :check-balance} #Interceptor{:name :hash-txs} #Interceptor{:name :chain-tx}], :route-name :transactions-post, :path-params {}, :io.pedestal.http.route.prefix-tree/satisfies-constraints? #object[clojure.core$constantly$fn__5672 0x6f1e7c72 "clojure.core$constantly$fn__5672@6f1e7c72"]}, :servlet #object[io.pedestal.http.servlet.FnServlet 0x718000a1 "io.pedestal.http.servlet.FnServlet@718000a1"], :servlet-request #object[org.eclipse.jetty.server.Request 0x71f2f53b "Request(POST //localhost:8910/v1/transactions)@71f2f53b"], :url-for #object[clojure.lang.Delay 0x13737d55 {:status :pending, :val nil}], :io.pedestal.interceptor.chain/execution-id 9, :servlet-config #object[org.eclipse.jetty.servlet.ServletHolder$Config 0x6672e704 "org.eclipse.jetty.servlet.ServletHolder$Config@6672e704"], :async? #object[io.pedestal.http.impl.servlet_interceptor$servlet_async_QMARK_ 0x13938483 "io.pedestal.http.impl.servlet_interceptor$servlet_async_QMARK_@13938483"]}, :line 253}
sequence_1  | clojure.lang.ExceptionInfo: java.lang.NullPointerException in Interceptor :auth - 
sequence_1  |   at io.pedestal.interceptor.chain$throwable__GT_ex_info.invokeStatic(chain.clj:35)
sequence_1  |   at io.pedestal.interceptor.chain$throwable__GT_ex_info.invoke(chain.clj:32)
sequence_1  |   at io.pedestal.interceptor.chain$try_f.invokeStatic(chain.clj:57)
sequence_1  |   at io.pedestal.interceptor.chain$try_f.invoke(chain.clj:44)
sequence_1  |   at io.pedestal.interceptor.chain$process_all_with_binding.invokeStatic(chain.clj:171)
sequence_1  |   at io.pedestal.interceptor.chain$process_all_with_binding.invoke(chain.clj:146)
sequence_1  |   at io.pedestal.interceptor.chain$process_all$fn__9198.invoke(chain.clj:188)
sequence_1  |   at clojure.lang.AFn.applyToHelper(AFn.java:152)
sequence_1  |   at clojure.lang.AFn.applyTo(AFn.java:144)
sequence_1  |   at clojure.core$apply.invokeStatic(core.clj:665)
sequence_1  |   at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1973)
sequence_1  |   at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1973)
sequence_1  |   at clojure.lang.RestFn.invoke(RestFn.java:425)
sequence_1  |   at io.pedestal.interceptor.chain$process_all.invokeStatic(chain.clj:186)
sequence_1  |   at io.pedestal.interceptor.chain$process_all.invoke(chain.clj:182)
sequence_1  |   at io.pedestal.interceptor.chain$enter_all.invokeStatic(chain.clj:235)
sequence_1  |   at io.pedestal.interceptor.chain$enter_all.invoke(chain.clj:229)
sequence_1  |   at io.pedestal.interceptor.chain$execute.invokeStatic(chain.clj:379)
sequence_1  |   at io.pedestal.interceptor.chain$execute.invoke(chain.clj:352)
sequence_1  |   at io.pedestal.interceptor.chain$execute.invokeStatic(chain.clj:389)
sequence_1  |   at io.pedestal.interceptor.chain$execute.invoke(chain.clj:352)
sequence_1  |   at io.pedestal.http.impl.servlet_interceptor$interceptor_service_fn$fn__13545.invoke(servlet_interceptor.clj:351)
sequence_1  |   at io.pedestal.http.servlet.FnServlet.service(servlet.clj:28)
sequence_1  |   at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:873)
sequence_1  |   at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542)
sequence_1  |   at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
sequence_1  |   at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345)
sequence_1  |   at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
sequence_1  |   at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
sequence_1  |   at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
sequence_1  |   at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247)
sequence_1  |   at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
sequence_1  |   at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
sequence_1  |   at org.eclipse.jetty.server.Server.handle(Server.java:505)
sequence_1  |   at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:370)
sequence_1  |   at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:267)
sequence_1  |   at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
sequence_1  |   at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
sequence_1  |   at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
sequence_1  |   at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
sequence_1  |   at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
sequence_1  |   at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
sequence_1  |   at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
sequence_1  |   at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
sequence_1  |   at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:698)
sequence_1  |   at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:804)
sequence_1  |   at java.lang.Thread.run(Thread.java:748)
sequence_1  | Caused by: java.lang.NullPointerException: null
sequence_1  |   at clojure.core$subs.invokeStatic(core.clj:4987)
sequence_1  |   at clojure.core$subs.invoke(core.clj:4981)
sequence_1  |   at decimals.security$remove_colon.invokeStatic(security.clj:34)
sequence_1  |   at decimals.security$remove_colon.invoke(security.clj:33)
sequence_1  |   at decimals.security$header_key.invokeStatic(security.clj:42)
sequence_1  |   at decimals.security$header_key.invoke(security.clj:39)
sequence_1  |   at decimals.security$apikey_auth.invokeStatic(security.clj:56)
sequence_1  |   at decimals.security$apikey_auth.invoke(security.clj:54)
sequence_1  |   at decimals.interceptors$fn__21455.invokeStatic(interceptors.clj:162)
sequence_1  |   at decimals.interceptors$fn__21455.invoke(interceptors.clj:161)
sequence_1  |   at io.pedestal.interceptor.chain$try_f.invokeStatic(chain.clj:54)
sequence_1  |   ... 44 common frames omitted
sequence_1  | INFO  i.p.http.impl.servlet-interceptor  - {:msg "sending error", :message "Internal server error: exception", :line 215}

Somehow related to the fact that I'm using a false authentication. If I remove the auth header, server gives me {"message":"Invalid credentials."}.

Any ideas?

andriosrobert commented 4 years ago

Hey @lgrkvst! Thanks for the issue.

It looks like your API Keys are not valid:

echo -n 'MjyNj0Mwo=' | base64 --decode # 2<??C0

You need to provide your API key as the basic auth username value. You do not need to provide a password.

The default API Key configured in docker-compose is 123. I added a bit more details to the docs:

https://docs.decimals.app/docs/sequence/docs/start-.md#authentication

It looks like we have a bug in the code parsing the keys. It should give you a 403 instead of a 500. I will fix this soon.