+ Start a Discussion
Kelly KKelly K 

POST http://localhost:8080/services/Soap/u/35.0 404 (Not Found)

Hi All,

I'm about at my wits end with this as there seems to be no documentation or other posts that comes close to this topic.

I'd like to make some changes to an HTML page that is hosted on our company's domain (not salesforce's - www.navicure.com) that we use as a log in page for our portal users. In doing so, I'm trying to connect to the AJAX toolkit so I can leverage sforce.connection.login(username, password).

When I was running it locally, I got the error: XMLHttpRequest cannot load file:///C:/services/Soap/u/35.0. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.

Fine. So I move it to be hosted under my local tomcat server so it'll be hosted from http.

Now when trying to run it on the localhost, I'm getting the error POST http://localhost:8080/services/Soap/u/35.0 404 (Not Found). 

What am I doing wrong?

<!DOCTYPE html>
<head>
	<script type="text/javascript" src="https://na19.salesforce.com/soap/ajax/35.0/connection.js"></script>		
	<link href="bootstrap.css" rel="stylesheet">			

	<!--Override the sforce.Transport function due to an error in the AJAX toolkit for "user-agent"-->
	<script>
		sforce.Transport = function(url) {
		this.url = url;
		this.connection = null;

		this.newConnection = function() {
			try {
				this.connection = new ActiveXObject('Msxml2.XMLHTTP');
			} catch(e) {
				try {
					this.connection = new ActiveXObject('Microsoft.XMLHTTP');
				} catch(e) {
					this.connection = new XMLHttpRequest();
				}
			}

			return this.connection;
		};

		this.send = function (envelope, callback, async, timeout) {
			this.newConnection();
			if (async) {
				this.connection.onreadystatechange = this.httpConnectionCallback;
			}
			var holder = new sforce.internal.ConnectionHolder(this.connection, callback);
			sforce.internal._connections.push(holder);
			this.connection.open("POST", this.url, async);
			this.connection.setRequestHeader("Content-Type", "text/xml; charset=UTF-8");
			this.connection.setRequestHeader("SOAPAction", "\"\"");
			this.connection.setRequestHeader("Accept", "text/xml");
		 //   this.connection.setRequestHeader("User-Agent", "SFAJAX 1.0");
			this.connection.send(envelope);
			if (async && typeof(timeout) !== "undefined") {
				this.setTimeoutOn(holder, timeout);
			}
			if (!async) {
				this.httpConnectionCallback();
			}
		};

		this.setTimeoutOn = function (holder, timeout) {
			function abortConnection() {
				if (holder.connection.readyState !== 4) {
					holder.timedout = true;
					holder.connection.abort();
				}
			}
			setTimeout(abortConnection, timeout);
		};

		this.httpConnectionCallback = function () {

			for (var i = 0; i < sforce.internal._connections.length; i++) {
				var holder = sforce.internal._connections[i];
				if (holder !== null) {
					if (holder.timedout) {
						sforce.internal._connections[i] = null;
						sforce.internal._connections.slice(i,1);
						holder.callback.httpCallback("Remote invocation timed out", false);
					} else  if (holder.connection.readyState == 4) {
						sforce.internal._connections[i] = null;
						sforce.internal._connections.slice(i,1);
						var success = holder.connection.status == 200;
						if (sforce.debug.trace) {
							sforce.debug.log("Response : status - " + holder.connection.status);
							sforce.debug.logXml(holder.connection.responseText);
						}
						if (sforce.debug.apexTrace) {
							sforce.debug.logApex(holder.connection.responseText);
						}
						if (holder.connection.responseXML && holder.connection.responseXML.documentElement) {
							holder.callback.httpCallback(holder.connection.responseXML.documentElement, success);
						} else {
							holder.callback.httpCallback("Remote invocation failed, due to: " + holder.connection.responseText +
														 " status code: ", holder.connection.status);
						}
					}
				}
			}
		};
	};
	</script>
	
	<script type="text/javascript">		
		function login() {		
			var username = "";
			var password = "";
			var username = document.getElementById("username").value;
			var password = document.getElementById("password").value;
			var returnURL = "https://na19.salesforce.com/apex/portalMain";
			
			if(username.length > 0 || password.length > 0) {
				try {
					console.log("username: " + username);
					console.log("password: " + password);
					var result = sforce.connection.login(username, password);
					
				}
				catch(error) {
					if (error.faultcode.indexOf("INVALID_LOGIN") != -1) {
						//$("#notification").text("Your login attempt has failed. The username or password may be incorrect, or your location or login time may be restricted. Please contact the administrator at your company for help");
						alert("log in invalid");
						return false;
					} else {
						alert(error);
					}
				}
				
				window.location = "https://na19.salesforce.com/secur/frontdoor.jsp?sid=" + result.sessionId + "&retURL=" + returnURL;
			}
		
			return false;
		}		
	</script>
</head>
 

 

 

Daniel BallingerDaniel Ballinger
I'm not familiar with using the AJAX Toolkit in a context outside of Salesforce. Typically it would be used client side in a Visualforce page.

The AJAX Toolkit is a JavaScript wrapper around the SOAP based partner API. One option would be to create the raw POST request for the Partner API login method and then use that to get the valid SessionId.

I did find another option looking in https://na19.salesforce.com/soap/ajax/35.0/connection.js. At the end of that file is the line that configures the URL for the Partner API. This expects the toolkit to be hosted within a Salesforce domain.
sforce.connection.serverUrl = (typeof window.UserContext != "undefined") ? UserContext.getUrl("/services/Soap/u/35.0") : "/services/Soap/u/35.0";
Before calling the sforce.connection.login method you can manually set the correct login URL. E.g.:
 
sforce.connection.serverUrl = "https://login.salesforce.com/services/Soap/u/35.0"
You might still run into CORS restrictions in the browser. 


 
Kelly KKelly K

I reached the same conclusion not long after the post. I ended up taking connection.js and adding it as a local fild and corrected all of the URLs to be server specific instead of agnostic.

That being said, I am running into CORS restrictions as I'm running this off of tomcat to have it hosted on http. I used tomcat with another program for a different project last year, but the application we used managed all of the WEB-INF files and created anything else needed. I think I'm missing something along those lines as I've already added the .jar files and the filters (http://software.dzhuvinov.com/cors-filter-installation.html) needed and I'm still getting this error:

XMLHttpRequest cannot load https://na19.salesforce.com/services/Soap/u/35.0. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

Supposedly we "have a guy" that knows about this stuff, but I am willing to accept help from anyone who can. 
 

Daniel BallingerDaniel Ballinger
There is Spring ’15 Preview – CORS for the Force.com REST API (https://developer.salesforce.com/blogs/developer-relations/2015/01/spring-15-preview-cors-force-com-rest-api.html).

However, the login call is going to the SOAP Partner API. I'm not sure if the Salesforce CORS support for the REST API extends to the SOAP API.
Kelly KKelly K

Neat. 

 

I decided to move the project into Eclipse as it appears it can host at http and the CORS issues are already addressed. The only thing that took a moment to figure out was that it cannot do console.log, so you have to force it over to firefox to see that info.

 

What I found after looking at this is that I was getting an error 

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/

 

What I found on other threads was that people were updating the async variable to to true. I did that and I'm not getting an error anymore, but sforce.connection.login is returning undefined, even with valid credentials. 

Daniel BallingerDaniel Ballinger
Without knowing the full details, wouldn't an async call require someform of callback? Now that it is no longer synchronous you can't get the result directly back from the login call without awaiting the async event to complete and getting the response back.

I'm not sure on the correct terminology for JavaScript, but I suspect that will be the issue.