Getting Error 401 when calling the REST API from a different server
Hi there,
so i try to build a small application that shows the build status of all builds.
I added this to the internal properties
rest.cors.optionsRequest.allowUnauthorized=true
rest.cors.origins=https://app.mydomain.live
and this is how i try to call the rest api with javascript:
and this is how i try to call the rest api with javascript:
function fetchBuild(url) {
var xhttp = new XMLHttpRequest();
var auth = btoa(username + ":" + password);
xhttp.open("GET", url, true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("Authorization", "Basic " + auth);
xhttp.setRequestHeader("Accept", "application/json");
var xhttp = new XMLHttpRequest();
var auth = btoa(username + ":" + password);
xhttp.open("GET", url, true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("Authorization", "Basic " + auth);
xhttp.setRequestHeader("Accept", "application/json");
//var getUrl = window.location;
// var baseUrl = getUrl.protocol + "//" + getUrl.host
//xhttp.setRequestHeader('Access-Control-Allow-Origin', baseUrl);
//xhttp.setRequestHeader('Access-Control-Allow-Credentials', 'true');
// xhttp.withCredentials = true;
xhttp.send();
var ret = xhttp.responseText;
var response = "";
if (ret.length > 0) {
response = JSON.parse(xhttp.responseText);
}
return response;
}
The thing is i always end up getting this error:
Failed to load https://teamcity.bla.com/httpAuth/app/rest/latest/builds/buildType:MYBUILDID/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://app.mydomain.live' is therefore not allowed access. The response had HTTP status code 401.
With Postman from my local machine it works. But not from the Server in the Cloud where my Javascript Widget is hosted... What am i doing wrong?
Please sign in to leave a comment.
Make sure you restart the TeamCity server after adding "rest.cors.optionsRequest.allowUnauthorized=true" internal property.
Also, it seems you should not be adding Access-Control-Allow-* headers in your script.
Hi Yegor,
i restarted already after adding the property. Also as you can see in the code of my script that the part you mentioned is commented out.
Try enabling "debug-rest" logging preset and checking the teamcity-rest.log for related entries. If it's not clear what is going on, attach the log here and provide a dump of the actual HTTP request sent and response received.
Alright i did what you requested and it seemed like i had to add my own domain name because that's what the log said:
But that sadly didn't help.
Actually when i make a request from my local machine i'm on right now with postman - and the same url i give the XmlHttpRequest (now changed to jquery/ajax but that didn't help either...) it works and i get a good json response from teamcity. But everytime i do it on a remote machine (it's a website calling a js file which gets executed - i edit the js file and that's where the code for getting the rest data is in.) i only get errors :/
Like these:
OPTIONS https://teamcity.myteamcity.com/httpAuth/app/rest/latest/builds/buildType:CompileTests/ 401 ()
Failed to load https://teamcity.myteamcity.com/httpAuth/app/rest/latest/builds/buildType:CompileTests/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://app.mydomain.live' is therefore not allowed access. The response had HTTP status code 401.
I added https://app.mydomain.live already to the origin....
Also i changed my code to this:
function fetchBuild(theurl) {
var getUrl = window.location;
var baseUrl = getUrl.protocol + "//" + getUrl.host
var auth = btoa(username + ":" + password);
var response = "";
jQuery.support.cors = true;
$.ajax({
type: "GET",
url: theurl,
headers: {
Accept: "text/plain; charset=utf-8",
"Content-Type": "text/plain; charset=utf-8"
},
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + auth);
},
success: function(data) {
//alert('success');
alert("succsessfull " + data);
if (ret.length > 0) {
response = JSON.parse(data);
}
},
error: function(msg, url, line) {
alert('error trapped in error: function(msg, url, line)');
alert('msg = ' + msg + ', url = ' + url + ', line = ' + line);
}
});
return response;
}
This is the only log entry my call is creating:
Hello,
The first log entry you included with "Got CORS request from origin 'https://teamcity.myteamcity.com'" seems to indicate some misconfiguration of the proxy or TeamCity's Tomcat as the URL noted is the URL of the server as I understand it.
Try using direct TeamCity server port, not one of the (transparent) proxy and review the proxy configuration. (see also related notes).
The later log lines indicate successful requests, but they might also be created by TeamCity Web UI.
One more note is that REST API does not support "text/plain", so Accept header should include "application/xml" or "application/json".
Well i set up a auto redirect to https. I had port 777 used before but now when i enter teamcity.myteamcity.com:777 i get forwarded to https://teamcity.myteamcity.com. Can i supply you with anything to further help you assisting fixing my problem? I will change the text/plain to application/json accordingly - forgot to change that in the new method...
This are my connectors inside the TeamCity\conf\server.xml and i can reach the server properly with the browser
<Connector port="777" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="443" />
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" scheme="https" secure="true" connectionTimeout="60000" redirectPort="8543" clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true" keystoreFile="C:\ProgramData\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\mycert.pfx" keystorePass="" socket.txBufSize="64000" socket.rxBufSize="64000" tcpNoDelay="1" />
I really can't figure out why this doesn't work :/ Please help me Yegor!
I changed the text/plain with application/json but it won't help. Also we don't have a proxy. I just have this subdomain pointing to the server, a windows 2016 server and teamcity installed on it. I just changed the server.xml for the connectors so https would work but i don't know if i introduced this bug or not...
I solved it. changed the port to 80, also removed httpauth from the url calling the rest api.
hi,
I am trying to fetch the visible artifact size for all the builds in teamcity for a particular month.
Below is the code i have written.
It works for few build ids and then it starts throwing http error 401 basic auth failed.
I have tried everything possible by even hard coding the values etc but nothing seems to be working.
It works when i hard code the value but when it encounters the same value in script, it throws error.
We are using below code but its working till some point and then starts failing with the basic auth failed error.
Sometimes it works till 15 hits and sometimes it works till 600 hits but then starts throwing authentication failure error for all the subsequent builds.
Below is the code and output-
import xml.etree.ElementTree as ET
import urllib, urllib2, os, sys, subprocess, time
import json,base64,re
import csv
from random import randint
from time import sleep
from random import randint
from datetime import datetime, timedelta
teamcity_url = "https://teamcity-icgtts.nam.nsroot.net:8443"
teamcity_password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
teamcity_username = "*******"
teamcity_password = "*******"
teamcity_password_mgr.add_password(None, teamcity_url, teamcity_username, teamcity_password)
teamcity_handler = urllib2.HTTPBasicAuthHandler(teamcity_password_mgr)
teamcity_opener = urllib2.build_opener(teamcity_handler)
def teamcity_request(request_string, request_type):
request = urllib2.Request(request_string, data='false')
request.add_header('Content-Type', 'application/xml')
request.get_method = lambda: request_type
url = teamcity_opener.open(request)
raw_xml = url.read()
url.close()
return raw_xml
def getParameters():
teamcity_response_builds = teamcity_request(teamcity_url+"/httpAuth/app/rest/builds/?locator=sinceDate:20190418T190000%2B0500%2cbranch:default:any%2cstatus:SUCCESS%2ccount:100000", 'GET')
teamcity_response_builds_xml = ET.fromstring(teamcity_response_builds)
i=0
for build_xml in teamcity_response_builds_xml.findall('build'):
try:
buildtypeid=build_xml.attrib['id']
print("buildtype id is"+ buildtypeid)
teamcity_response_parameters = teamcity_request(teamcity_url+"/httpAuth/app/rest/builds/id:"+buildtypeid+"/statistics/VisibleArtifactsSize", 'GET')
print teamcity_response_parameters
if (teamcity_response_parameters.isdigit()):
i+=1
else:
pass
except Exception as e:
print(e)
print("there was an error")
pass
return i
count=getParameters()
print ( count)
output-
buildtype id is636302
41779200
buildtype id is636294
58565337
buildtype id is636300
60405760
buildtype id is636276
HTTP Error 404:
there was an error
buildtype id is636296
HTTP Error 404:
there was an error
buildtype id is636287
HTTP Error 404:
there was an error
buildtype id is636288
HTTP Error 404:
there was an error
buildtype id is636247
HTTP Error 404:
there was an error
buildtype id is636293
HTTP Error 404:
there was an error
buildtype id is636292------------------------------it starts throwing authentication error at this point though it has
artifacts and it should print the value like it has printed for previous
ids
HTTP Error 401: basic auth failed
there was an error
buildtype id is636284
HTTP Error 401: basic auth failed
there was an error
buildtype id is636260
HTTP Error 401: basic auth failed
there was an error
buildtype id is636259
HTTP Error 401: basic auth failed
there was an error
buildtype id is636256
HTTP Error 401: basic auth failed
there was an error
Hi Abhishek,
If I am not mistaken, when you contacted us in support (ticket #2142036) with this message, our response was that there seems to be issues with the authentication provider in use and it makes sense to check logs/teamcity-auth.log on the server to get the reason of the 401 errors. Nothing have changed since that, that answer still holds true and I encourage you to continue communications in that ticket.
Hi Guys,
I have a similar problem, enabled the cors in the internal properties but am seeing a 401 on the hub and I see the below in the rest log. Whats stranger though is that the rest log is using the client pc ip ( the one viewing the hub ) rather than the hub server? I would have thought the call would come from the Hub server instance?
Hi Mario,
What's making the rest calls? Is it something on your PC or is hub somehow running them?
Besides, for the issues, 500 errors are logged into the server's main log, so I'd recommend checking there and sharing the stacktraces from there. It might make sense to create a separate issue to not send notifications to everyone involved in this thread.