Cloud9 Python XMLRPC Server 302 redirect - python

I'm using python and cloud9 trying to setup a simple XMLRPC server. If I run this all on my local host, I have no issues. On the Cloud9 host, I get get a ProtocolError 302 Moved temporarily.
Any ideas?
The server code is:
from SimpleXMLRPCServer import SimpleXMLRPCServer
import logging
import os
ip = os.getenv("IP", "0.0.0.0")
port = int(os.getenv("PORT", 8080))
logging.basicConfig(level=logging.DEBUG)
server = SimpleXMLRPCServer((ip, port), logRequests=True)
def list_contents(dir_name):
logging.debug('list_contents(%s)', dir_name)
return dir_name
server.register_function(list_contents)
try:
print 'Use Control-C to exit'
server.serve_forever()
except KeyboardInterrupt:
print 'Exiting'
The client code is:
import xmlrpclib
url = "https://xxxxx.c9.io/"
srv = xmlrpclib.ServerProxy(url, verbose=True)
print srv.list_contents("asdf")

The 302 response is most likely redirecting you to an authentication/authorisation URL to assess your permissions to access the application. This is always the response if you configured your workspace / access via web to be private (no unauthenticated access).
You can either share it publicly (click Share -> click 'application' to be public) or provide username and password in the requested URL in the client:
url = "https://username:password#workspace-c9-user.c9.io/"

Related

Tornado secure websocket timeout

My server got 2 Ip's (ip1 & ip2) i recently added ip2. When i try to open my tornado websocketserver on ip1 (where apache2 is running) everything is fine, i specify a port e.g. 22000 and can connect to my socket via wss://domain.tld:22000/sub
However as soon as i configured tornado to listen on ip2 (where apache is not running), because i have to use the port 443, which is blocked by apache on ip1, I can't connect to it via wss://sockets.domain.tld:443/sub. The DNS A record points to ip2.
The connection times out. No matter which port or protocol (wss / ws) i use.
My python code:
from tornado import web
from tornado import ioloop
from tornado import websocket
from tornado import httpserver
import ssl
import json
import random
import re
import os
application = web.Application([(r"/sub", Client)])
http_server = httpserver.HTTPServer(application, ssl_options = {
"certfile": os.path.join(LIB_DIR, "certificate.crt"),
"keyfile": os.path.join(LIB_DIR, "certificate.key"),
})
http_server.bind(443, address = "ip2")
print("Listening to ip2:443")
ioloop.IOLoop.current().start()
My Server is running on Ubuntu 12.2, I opened the ports and checked with an external tool if they are open.
How can i fix this? Has it something to do with my server?
UPDATE
I'm quite sure it has to do with http_server.bind(...), the code does work with .listen(port), but ip1 and bind does also not work.
According to the documentation, after the call to bind, you should call start on the server. So
http_server.bind(443, address = "ip2")
print("Listening to ip2:443")
http_server.start()
ioloop.IOLoop.current().start()
should work.

printing URL parameters of a HTTP request using Python + Nginx + uWSGI

I have used this link and successfully run a python script using uWSGI. Although i just followed the doc line by line.
I have a GPS device which is sending data to a remote server. Document of the same device say that it connect to server using TCP which therefore would be http as simple device like a GPS device would not be able to do https (i hope i am right here.) Now as i have configure my Nginx server to forward all incoming HTTP request to python script for processing via uWSGI.
What i want to do is to simply print the url or query string on the HTML page. As i don't have control on the device side (i can only configure device to send data on a IP + Port), i have no clue how data is coming. Below is my access log
[23/Jan/2016:01:50:32 +0530] "(009591810720BP05000009591810720160122A1254.6449N07738.5244E000.0202007129.7200000000L00000008)" 400 172 "-" "-" "-"
Now i have look at this link on how to get the url parameters values, but i don't have a clue that what is the parameter here.
I tried to modified my wsgi.py file as
import requests
r = requests.get("http://localhost.com/")
# or r = requests.get("http://localhost.com/?") as i am directly routing incoming http request to python script and incoming HTTP request might not have #any parameter, just data #
text1 = r.status_code
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["<h1 style='color:blue'>Hello There shailendra! %s </h1>" %(text1)]
but when i restarted nginx, i get internal server error. Can some one help me to understand wrong i am doing here (literally i have no clue about the parameters of the application function. Tried to read this link, but what i get from here is that environ argument take care of many CGI environment variables.)
Can some one please help me to figure out what wrong am i doing and guide me to even a doc or resource.
Thanks.
why are you using localhost ".com" ?
Since you are running the webserver on the same machine,
you should change the line to
r = requests.get("http://localhost/")
Also move below lines from wsgi.py and put them in testServerConnection.py
import requests
r = requests.get("http://localhost/")
# or r = requests.get("http://localhost.com/?") as i am directly routing incoming http request to python script and incoming HTTP request might not have #any parameter, just data #
text1 = r.status_code
Start NGINX
and you also might have to run (i am not sure uwsgi set up on nginx)
uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi
run testConnection.py to send a test request to localhost webserver and print the response
i got the answer for my question. Basically to process a TCP request, you need to open a socket and accept the TCP request on a specific port (as you specified on the hardware)
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
#data which is received
print self.data
if __name__ == "__main__":
#replace IP by your server IP
HOST, PORT = <IP of the server>, 8000
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
After you get the data, you can do any thing with the data. As my data format was shared in the GPS datasheet, i was able to parse the string and get the Lat and long out of it.

Python simple HTTPS forwarder

Below is the simple script I'm using to redirect regular HTTP requests on port 8080, it redirects(causes them to be at least) them depending on the source IP address right away.
It works (for HTTP), however I would like to have the same behavior for HTTPS requests coming over 443 port. Assume that if the redirection was not present, incoming clients to this simple server would be able to handshake with the target they are being redirected to via a self signed certificate.
import SimpleHTTPServer
import SocketServer
LISTEN_PORT = 8080
source = "127.0.0.1"
target = "http://target/"
class simpleHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_POST(self):
clientAddressString = ''.join(str(self.clientAddress))
if source in clientAddressString:
# redirect incoming request
self.send_response(301)
new_path = '%s%s' % (target, self.path)
self.send_header('Location', new_path)
self.end_headers()
handler = SocketServer.TCPServer(("", LISTEN_PORT), simpleHandler)
handler.serve_forever()
I can use a self signed certificate and have access to files "server.crt" and "server.key" that are normally used for this connection(without the middle redirecting python server). I am not sure what happens when I put a redirection in between like this, although I assume it has to be part of the hand-shaking chain.
How can I achieve this behavior?
Is there anything I should modify apart from the new target and the response code within request headers?
I will split my answer into Networking and Python parts.
On the Networking side, you cannot redirect at the SSL layer - hence you need a full HTTPs server, and redirect the GET/POST request once the SSL handshake is complete. The response code, and the actual do_POST or do_GET implementation would be exactly the same for both HTTP and HTTPs.
As a side note, don't you get any issues with redirecting POSTs? When you do a 301 on POST, the browser will not resend the POST data to your new target, so something is likely to break at the application level.
On the Python side, you can augment an HTTP server to an HTTPs one by wrapping the socket:
import BaseHTTPServer, SimpleHTTPServer
import ssl
handler = BaseHTTPServer.HTTPServer(("", LISTEN_PORT), simpleHandler)
handler.socket = ssl.wrap_socket (handler.socket, certfile='path/to/combined/PKCS12/container', server_side=True)
handler.serve_forever()
Hope this helps.

SOAP web service behind proxy, access using python-suds

I have this strange case scenario with python suds.
I have a soap service (java) running on a local ip, say http://10.0.0.1:8080/services/
I use suds http base auth within the local network and it's working fine.
from suds.client import Client
c = Client(url, username="user", password="pass")
But I want to make it accessible from outside, so I asked the system admin : "Can you set up a external IP use reverse proxy for this soap service"
"Yes, but the company firewall doesn't allow port 8080, so your rule will be:
http://10.0.0.1:8080/services/* <-> https://example.com/services/*
Then the rule is setup but I just can't make the client to work. I tried all kinds of transport:
from suds.transport.https import WindowsHttpAuthenticated
from suds.transport.http import HttpAuthenticated
#from suds.transport.https import HttpAuthenticated
from suds.client import Client
http = HttpAuthenticated(username="jlee", password="jlee")
#https = HttpAuthenticated(username="jlee", password="jlee")
ntlm = WindowsHttpAuthenticated(username="jlee", password="jlee")
url = "https://example.com/services/SiteManager?wsdl"
c = Client(url, transport = http)
it always returns:
suds.transport.TransportError: HTTP Error 403: Forbidden ( The server denied the specified Uniform Resource Locator (URL). Contact the server administrator. )
I tried to access the URL https://example.com/services/SiteManager?wsdl from chrome, it returns 403 too!
But if I sign in first using other routes (my server is running other http pages on tomcat), and then access the URL again the wsdl desc page shows up!
Can anybody tell me what's wrong with this? is it to do with the configuration of the reverse proxy server or the suds transport?
Thanks very much!
Jackie
Found the solution by talking to system admin(who's in charge of setting up the reverse proxy), he said there is an checkbox option in MS DMZ(reverse proxy server) for allow http base auth.

Google API oauth httpd server conflicts with SABNzbd+ in Python

I'm writing a Python app that interacts with a Google API and requires user authentication via oauth2.
I'm currently setting up a local authentication server to receive an oauth2 authentication code back from Google's oauth server, basically doing the oauth dance like this.
It usually works pretty well, but I guess I'm not understanding exactly how it's interacting with my ports, because it will happily assign my local authentication server to run on port 8080 even if some other app (in the case of my testing, SABNzbd++) is using that port.
I thought assigning the port to a used port number would result in an error and a retry. What am I doing wrong (or, alternatively, what is SABNzbd++ doing that keeps the fact that it's listening on port 8080 hidden from my app?)
The relevant code is as follows.
import socket
import BaseHTTPServer
from oauth2client.tools import ClientRedirectServer, ClientRedirectHandler
port_number = 0
host_name = 'localhost'
for port_number in range(8080,10000):
try:
httpd = ClientRedirectServer((host_name, port_number),
ClientRedirectHandler)
except socket.error, e:
print "socket error: " + str(e)
pass
else:
print "The server is running on: port " + str(port_number)
print "and host_name " + host_name
break
To clarify, the following are my expected results
socket error: [port already in use] (or something like that)
The server is running on: port 8081
and host_name localhost
and then going to localhost:8080 resolves to SABnzbd+, and localhost:8081 resolves to my authentication server.
I'm getting, howver:
the server is running on: port 8080
and host_name localhost
but going to localhost:8080 resolves to SABNzbd+
Thanks in advance!

Categories

Resources