Why does the cleandb extension refuse to delete my neo4j graph database? - neo4j

When trying to purge neo4j (1.8.2) with the cleandb extension (for neo4j 1.8), it fails:
[path] ? curl -v -X DELETE 'http://localhost:7475/db/cleandb/12sE$lkj3%'
* About to connect() to localhost port 7475 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 7475 (#0)
> DELETE /db/cleandb/12sE$lkj3% HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:7475
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Content-Length: 0
< Server: Jetty(6.1.25)
<
* Connection #0 to host localhost left intact
Obviously, I do not only get a 500 error code, also the db is not purged.
Of course, access URL and "secret-key" of the plugin are set up as used in the curl request:
org.neo4j.server.thirdparty_jaxrs_classes=org.neo4j.server.extension.test.delete=/db/cleandb
org.neo4j.server.thirdparty.delete.key=12sE$lkj3%
I would conveniently add the cleandb tag, but I lack the 1500 reputation.
Any ideas? Thanks in advance!
EDIT
(The reason I use cleandb is to set up unittests in neo4django).
/EDIT

Hm, I have the cleandb extension working locally against 1.8.2 and 1.9. For example, you can run
from neo4django.db import connection
from pdb import set_trace; set_trace()
connection.cleandb()
and trace the cleandb Python call, and it gets a 200 and accompanying response body,
{\n "node-indexes" : [ ],\n "nodes" : 4,\n "relationship-indexes" : [ ],\n "relationships" : 0,\n "maxNodesToDelete" : 1000\n}
I'm not sure what the difference between curl and the Python call might be- any chance you could try the above in a module, run it, and see what happens?
EDIT:
The cleandb extension is unmanaged, so you can't (IIRC?) set the URL to '/db/cleandb', it needs to be on its own root- I use '/cleandb'. LMK if that helps!
EDIT:
Aw, disregard that, '/db/' urls seem to work fine. Maybe you could use the 'install_local_neo4j.bash' script (https://github.com/scholrly/neo4django/blob/master/install_local_neo4j.bash) to install a copy of Neo4j and set it up the same way, if that works for you? And if so, maybe we can see how the setups differ...

It only works with Neo4j versions up to 1.7 I think.
Didn't update it anymore b/c you can do that cleanup with cypher now, see: http://neo4j.org/resources/cypher
start n=node(*)
match n-[r?]->()
where id(n) <> 0
delete n,r

Related

How can I set the User-Agent header when downloading a file in Clojure?

Using the method described in this answer (clojure.java.io/input-stream), how would I go about setting the User-Agent request header?
You can't. clojure.java.io is a very simplistic API, for doing the easiest stuff. If you want any real customization you'll need to use a real HTTP library.
You can, but only to a certain extent, setting a property.
From this answer https://stackoverflow.com/a/47300260/483566 I tried running netcat in a terminal: nc -l -p 8080
On the REPL, I tried the following:
$ lein repl
nREPL server started on port 42819 on host 127.0.0.1 - nrepl://127.0.0.1:42819
REPL-y 0.4.3, nREPL 0.6.0
Clojure 1.10.0
OpenJDK 64-Bit Server VM 11.0.4+11-post-Ubuntu-1ubuntu218.04.3
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> (System/setProperty "http.agent" "Clojure REPL")
nil
user=> (slurp "http://localhost:8080/")
Netcat is not actually serving content, so the REPL will block, but if you see the terminal where netcat runs, you'll see something like:
GET / HTTP/1.1
User-Agent: Clojure REPL Java/11.0.4
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
For actual customization, you probably want to use an HTTP client library that provides access to the HTTP headers (most will do).

Configuring uWSGI to not interpret PATH_INFO

How can I configure uwsgi to pass in the request path unmodified as PATH_INFO? I.e. if there is a request https://example.com/foo%5F/../bar?x=y, I want PATH_INFO to be literally /foo/../%5Fbar, and not /_bar.
The uWSGI documentation says uWSGI is able to rewrite request variables in lot of advanced ways, but I am unable to find any way to set individual request variables, at least not without modifying the source code of uwsgi.
The reason I want to do is that I have a frontend application which takes user input and then sends a request to http://backend.app/get/USER_INPUT. Trouble is, there is an uwsgi in between, and when the user input is ../admin/delete-everything, the request goes to http://backend.app/admin/delete-everything!
(This uwsgi change I desire will not be the only fix; the frontend app should certainly validate user input, and the backend app should not offer /admin to the frontend app in the first place. But as a measure of defense-in-depth, I'd like my requests to pass uwsgi unmodified.)
I am running bare uWSGI without nginx, i.e. uwsgi --http 0.0.0.0:8000 --wsgi-file myapp/wsgi.py --master --processes 8 --threads 2.
For what it's worth, the backend app that looks into PATH_INFO is Django.
My previous answer holds true for the clients which do url parsing at the source. This answer is applicable, when you can actually get the correct request.
The wsgi.py is run by uwsgi and the application object is called as callable. This in case of Django is WSGIHanlder, which has below code
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.load_middleware()
def __call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
print(environ)
request = self.request_class(environ)
response = self.get_response(request)
response._handler_class = self.__class__
status = '%d %s' % (response.status_code, response.reason_phrase)
response_headers = [
*response.items(),
*(('Set-Cookie', c.output(header='')) for c in response.cookies.values()),
]
start_response(status, response_headers)
if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
response = environ['wsgi.file_wrapper'](response.file_to_stream)
return response
I created a sample view to test the same
from django.http import HttpResponse
def index(request, **kwargs):
return HttpResponse("Hello, world. You're at the polls index. " + request.environ['PATH_INFO'])
def index2(request, **kwargs):
return HttpResponse("Hello, world. You're at the polls index2. " + request.environ['PATH_INFO'])
and registered them using below code
from django.urls import include, path
from polls.views import index2, index
urlpatterns = [
path('polls2/', index2, name='index2'),
path('polls2/<path:resource>', index2, name='index2'),
path('polls/', index, name='index'),
path('polls/<path:resource>', index, name='index'),
]
So what you need is overriding this class. Below is an example
import django
from django.core.handlers.wsgi import WSGIHandler
class MyWSGIHandler(WSGIHandler):
def get_response(self, request):
request.environ['ORIGINAL_PATH_INFO'] = request.environ['PATH_INFO']
request.environ['PATH_INFO'] = request.environ['REQUEST_URI']
return super(MyWSGIHandler, self).get_response(request)
def get_wsgi_application():
"""
The public interface to Django's WSGI support. Should return a WSGI
callable.
Allows us to avoid making django.core.handlers.WSGIHandler public API, in
case the internal WSGI implementation changes or moves in the future.
"""
django.setup()
return MyWSGIHandler()
application = get_wsgi_application()
After this can you can see the below results
$ curl --path-as-is "http://127.0.0.1:8000/polls/"
Hello, world. You're at the polls index. /polls/
$ curl --path-as-is "http://127.0.0.1:8000/polls2/"
Hello, world. You're at the polls index2. /polls2/
$ curl "http://127.0.0.1:8000/polls2/../polls/"
Hello, world. You're at the polls index. /polls/
$ curl --path-as-is "http://127.0.0.1:8000/polls2/../polls/"
Hello, world. You're at the polls index. /polls2/../polls/%
As you can see the change to PATH_INFO doesn't change which view is picked. As polls2 still picks index function
After digging a bit more, I realised there is another path and path_info variable. The class for the same is picked using path_info
So we update our function like below
class MyWSGIHandler(WSGIHandler):
def get_response(self, request):
request.environ['ORIGINAL_PATH_INFO'] = request.environ['PATH_INFO']
request.environ['PATH_INFO'] = request.environ.get('REQUEST_URI', request.environ['ORIGINAL_PATH_INFO'])
request.path = request.environ['PATH_INFO']
request.path_info = request.environ.get('REQUEST_URI', request.environ['PATH_INFO'])
return super(MyWSGIHandler, self).get_response(request)
After this change, we get the desired results
$ curl --path-as-is "http://127.0.0.1:8000/polls2/../polls/"
Hello, world. You're at the polls index2. /polls2/../polls/
So your problem has mostly nothing to do with uwsgi or Django as such. To demonstrated the issue, I created a simple flask app with a catch all handler
from flask import Flask
app = Flask(__name__)
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def catch_all(path):
return 'You want path: %s' % path
if __name__ == '__main__':
app.run()
Now when you run this and make a curl request
$ curl -v http://127.0.0.1:5000/tarun/../lalwani
* Rebuilt URL to: http://127.0.0.1:5000/lalwani
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> GET /lalwani HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 22
< Server: Werkzeug/0.15.2 Python/3.7.3
< Date: Fri, 26 Jul 2019 07:45:16 GMT
<
* Closing connection 0
You want path: lalwani%
As you can see that the server never had a chance to even know we requested this. Now lets do it again and ask curl not to tamper the url
$ curl -v --path-as-is http://127.0.0.1:5000/tarun/../lalwani
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> GET /tarun/../lalwani HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 31
< Server: Werkzeug/0.15.2 Python/3.7.3
< Date: Fri, 26 Jul 2019 07:48:17 GMT
<
* Closing connection 0
You want path: tarun/../lalwani%
Now you can see that my app did receive the actual path. Now let's see the same case in a browser, with app not even running
As you can even though my service is not even running but the browser itself refactored the call to /lalwani instead of /tarun/../lalwani. So there is nothing that could have been done at your end to even correct the issue, until unless you are using a client which supports disabling the url parsing at source

Standalone MockServer: Where do I implement expectations?

I am trying to mock an external (REST) server used by my system under test.
I am choosing MockServer (http://www.mock-server.com/) for mocking the external REST server.
I am running mock server standalone as in:
$ java -jar ./mockserver-netty-5.3.0-jar-with-dependencies.jar
-serverPort 1080 -proxyPort 1090 -proxyRemotePort 80 -proxyRemoteHost www.mock-server.com 2018-05-23 14:05:57,703 INFO o.m.m.MockServer
MockServer started on port: 1080 2018-05-23 14:05:57,747 INFO
o.m.p.d.DirectProxy MockServer started on port: 1090
I am not sure, having read the documentation, where I should define the expectations (viz., the responses the mock should yield based on incoming requests).
Can anyone explain?
Thanx,
R
It can be done by PUT, ie:
curl -v -X PUT "http://localhost:1080/expectation" -d '{
"httpRequest" : {
"path" : "/some/path"
},
"httpResponse" : {
"body" : "some_response_body"
}
}'
More info https://www.mock-server.com/mock_server/creating_expectations.html and go for REST API type of expectation
I used Postman to create the expectation. For creating expectations send a PUT request to http://localhost:portnumber/mockserver/expectation.
You can check the expectation and logs using this URL http://localhost:portnumber/mockserver/dashboard in the browser.

Rest call for mod_rest in ejabberd not working

Hello guys in my project I have the JID of sender and receiver and the body of the message. I need to send the message without using any chat client, hence I am using mod_rest so that I can access mod_admin_extra. I configured it with Ejabberd server 14.05 and tried to run the following rest call
[root#centos ~]# wget localhost:5280/rest/ --server-response --post-data 'registered_users localhost'
--2016-06-20 17:03:33-- http://localhost:5280/rest/
Connecting to <<proxy ip>>... connected.
Proxy request sent, awaiting response...
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1015
Connection: close
Date: Mon, 20 Jun 2016 11:33:33 GMT
Length: 1015 [text/html]
Saving to: “index.html.3”
Where index.html.3 had the following message,
Problem 'error function_clause' occurred executing the command.
Stacktrace: [{ejabberd_commands,'-check_access_commands/5-fun-0-',
[{rest,[{registered_users,[all]},{connected_users,[all]}]}],
[{file,"src/ejabberd_commands.erl"},{line,372}]},
{lists,'-filter/2-lc$^0/1-0-',2,[{file,"lists.erl"},{line,1284}]},
{ejabberd_commands,check_access_commands,5,
[{file,"src/ejabberd_commands.erl"},{line,371}]},
{ejabberd_commands,execute_command,4,
[{file,"src/ejabberd_commands.erl"},{line,308}]},
{ejabberd_ctl,call_command,3,
[{file,"src/ejabberd_ctl.erl"},{line,293}]},
{ejabberd_ctl,try_call_command,3,
[{file,"src/ejabberd_ctl.erl"},{line,269}]},
{ejabberd_ctl,process2,3,
[{file,"src/ejabberd_ctl.erl"},{line,218}]},
{mod_rest,maybe_post_request,3,
[{file,"src/mod_rest.erl"},{line,135}]}]
Mod_admin_extra is added in ejabberd configuration file.Is this an issue of command not been identified.If yes the please explain how to add mod_Admin_extra commands in ejabberdctl I am new to erlang so its quite difficult for me to debug hence any help would be beneficial for me and if you guys know any better approach to send message other than using mod_rest please do let me know
Thanks alot
I got the issue. The ejabberd_commands.hrl and mod_admin_extra modules of ejabberd 14.05 do not support the commands I needed. Hence I added newer version of both modules and it started working
You can even try with command send__message

iOS cURL: unable to get local issuer certificate

I'm trying to setup secure connection to HTTPS server with curl on iOS (app is written in C++)
I figured out that I need to set cacert.pam (http://curl.haxx.se/ca/cacert.pem) file path for CURLOPT_CAPATH option:
curl_easy_setopt (curl, CURLOPT_CAPATH, "/var/mobile/Applications/811DEF2E-DE1D-4C86-A1FD-129478C8318D/MyApp.app/ca/cacert.pem");
curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2L);
But this just generates folowing verbose log (ip and url changed):
libcurl/7.29.0 OpenSSL/1.0.1e zlib/1.2.5
* About to connect() to myserver.com port 443 (#0)
* Trying 128.128.128.128...
* Connected to myserver.com (128.128.128.128) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /var/mobile/Applications/171CA93F-15F2-42A1-938B-01812AF1E555/MyApp.app/ca/cacert.pem
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
Same happens if I set CURLOPT_CAPATH to "../MyApp.app/ca" folder. File exists and can be read.
There seems to be a lack of information about this error..
What I am doing wrong?
OK, after some irritating searching I found the problem and solution.
This does not seem to work neither with folder nor with file path:
curl_easy_setopt (curl, CURLOPT_CAPATH, caCertPath);
But this works when supplying full path to PEM file:
curl_easy_setopt (curl, CURLOPT_CAINFO, caCertPath);
Hope this helps someone in the future
from manual:
The CURLOPT_CAPATH function apparently does not work in Windows due to
some limitation in openssl
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
CURLOPT_CAINFO option works

Resources