I'm deep in the rabbit hole with this. I'm creating a simple app that uses SOLR 4 as a NoSQL datastore and AngularJS v1.2.2 for the interface. I've loaded a bunch of documents from the command line and AngularJS makes it very easy to search/view these. I want to permit document editing but can't get the POST working. Chrome console shows 400 errors and the Network tab shows it's failing on OPTIONS method.
Network Headers:Request URL:http://localhost:8983/solr/mrm_assay/update
Request Method:OPTIONS
Status Code:400 Bad Request
Request Headers
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,es;q=0.6
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:8983
Origin:http://localhost:63342
Pragma:no-cache
Referer:http://localhost:63342/angular-solr2/app/index.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:origin, content-type, cache-control, accept, options
Access-Control-Allow-Methods:GET,POST,DELETE,PUT,HEAD,OPTIONS
Access-Control-Allow-Origin:http://localhost:63342
Access-Control-Max-Age:1800
Content-Type:application/xml; charset=UTF-8
Transfer-Encoding:chunked
Quick overview of architecture:
Both SOLR and AngularJS apps are running on my Mac.
SOLR is using the default Jetty instance and the Angular app runs within the server from WebStorm's IDE. CORS is enabled and includes GET,POST,DELETE,PUT,HEAD,OPTIONS.
Updates work when:
$ curl http://localhost:8983/solr/mrm_assay/update -H 'Content-type:application/json' -d '[ {
"keep_in_assay" {"set" : "N",
"detected_endog": "N",
"problems_w_is": "removed b/c requires addition post-Oasis",
"onc_std_set": "set1",
"fraction_id": "7",
"onclistgene": "UBL3",
"geneid": "UBL3_IS6",
"taxonid": "9606",
"peptide": "SSNVPADMINLR",
"degen_human": "1",
"gene_degeneracy": "1",
"percnt_id": "66.7",
"uuid": "6d20eb03-d3ee-4eb2-bc16-27cfaabab989"
} ]'
My Angular controller code looks like this:assayControllers.controller('AssayUpdateController', ['$scope', '$http',
function($scope, $http){
$scope.processForm = function(){
console.log($scope.assay);
$http({
method:'POST',
url:'http://localhost:8983/solr/mrm_assay/update',
data : $scope.assay,
headers : {'Content-Type': 'application/json' }
})
.success(function(data, status, headers){
console.log(data.message);
})
.error(function(data, status, headers, config){
console.log(status);
});
};
}
]);
Data is successfully sent from the form as I can see it on the console (although the JSON object isn't packaged in an array, which SOLR seems to expect...I also tried to push JSON-formatted data to an array and POST that but no luck)
I appreciate your help - even if it's just to direct my troubleshooting!
The answer on how to update an individual document to SOLR v4.7 using AngularJS v1.2.2 is multi-part. This has only been tested on my localhost!
I. Configure CORS on Jetty server that ships with SOLR
solr-4.7.0/example/solr-webapp/webapp/WEB-INF/web.xml
Notes: CrossOriginFilter has a parameter, chainPreflight, that is set to true by default. This needs to be set to false. This was the key to CORS forwarding POST instead of OPTIONS to SOLR.. Also, order matters!
<filter>
<filter-name>cross-origin</filter-name>
<filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
<init-param>
<param-name>allowedOrigins</param-name>
<param-value>http://localhost*</param-value>
</init-param>
<init-param>
<param-name>allowedMethods</param-name>
<param-value>GET,POST,DELETE,PUT,HEAD,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>allowedHeaders</param-name>
<param-value>origin, content-type, cache-control, accept, options, authorization, x-requested-with</param-value>
</init-param>
<init-param>
<param-name>supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>chainPreflight</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>cross-origin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
II. SOLR expects payload in array format, so you need to push Angular object into one. Basically, $scope.data becomes [$scope.data]
assayControllers.controller('AssayUpdateController', ['$scope', '$http', '$location',
function($scope, $http, $location){
$scope.processForm = function(){
$http.post("http://localhost:8983/solr/mrm_assay/update?commit=true", [$scope.assay])
.success(function(data, status, headers){
console.log(data.message);
$location.path("/assays")
})
.error(function(data, status, headers, config){
console.log(status);
});
};
}
]);
III. SOLR documents contain version field that can cause "conflict" errors on POST. This is due to a cache issue I wasn't able to track down (curl showed current value but browsers had old one; even on force refresh). Anyway, this is of more use to SOLR than me so the best bet is to not return it to the client in the first place. I don't think field exclusion is an option so I whitelisted all the fields I wanted to return in solrconfig.xml
<!-- A request handler that returns indented JSON by default -->
<requestHandler name="/query" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="wt">json</str>
<str name="indent">true</str>
<str name="df">text</str>
<str name="fl">uuid,keep_in_assay,detected_endog,problems_w_is,onc_std_set,fraction_id,detected_by_orbi_experiments,onclistgene,geneid,taxonid,peptide,\
degen_human,degen_mouse,gene_degeneracy,department,protein_ac,pepid,protid,percnt_id,peptide_ordered</str>
Now the app works like a charm!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With