Skip to content

Commit f6ff970

Browse files
authored
HBASE-22846 Internal Error 500 when Using HBASE REST API to Create Na… (#524)
Signed-off-by: stack <stack@apache.org>
1 parent 1cbed07 commit f6ff970

File tree

3 files changed

+37
-58
lines changed

3 files changed

+37
-58
lines changed

hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/NamespacesInstanceResource.java

Lines changed: 16 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -135,35 +135,9 @@ public Response get(final @Context ServletContext context,
135135
@Consumes({MIMETYPE_XML, MIMETYPE_JSON, MIMETYPE_PROTOBUF,
136136
MIMETYPE_PROTOBUF_IETF})
137137
public Response put(final NamespacesInstanceModel model, final @Context UriInfo uriInfo) {
138-
if (LOG.isTraceEnabled()) {
139-
LOG.trace("PUT " + uriInfo.getAbsolutePath());
140-
}
141-
servlet.getMetrics().incrementRequests(1);
142138
return processUpdate(model, true, uriInfo);
143139
}
144140

145-
/**
146-
* Build a response for PUT alter namespace with no properties specified.
147-
* @param message value not used.
148-
* @param headers value not used.
149-
* @return response code.
150-
*/
151-
@PUT
152-
public Response putNoBody(final byte[] message,
153-
final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
154-
if (LOG.isTraceEnabled()) {
155-
LOG.trace("PUT " + uriInfo.getAbsolutePath());
156-
}
157-
servlet.getMetrics().incrementRequests(1);
158-
try{
159-
NamespacesInstanceModel model = new NamespacesInstanceModel(namespace);
160-
return processUpdate(model, true, uriInfo);
161-
}catch(IOException ioe){
162-
servlet.getMetrics().incrementFailedPutRequests(1);
163-
throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
164-
}
165-
}
166-
167141
/**
168142
* Build a response for POST create namespace with properties specified.
169143
* @param model properties used for create.
@@ -175,39 +149,26 @@ public Response putNoBody(final byte[] message,
175149
MIMETYPE_PROTOBUF_IETF})
176150
public Response post(final NamespacesInstanceModel model,
177151
final @Context UriInfo uriInfo) {
178-
179-
if (LOG.isTraceEnabled()) {
180-
LOG.trace("POST " + uriInfo.getAbsolutePath());
181-
}
182-
servlet.getMetrics().incrementRequests(1);
183152
return processUpdate(model, false, uriInfo);
184153
}
185154

186-
/**
187-
* Build a response for POST create namespace with no properties specified.
188-
* @param message value not used.
189-
* @param headers value not used.
190-
* @return response code.
191-
*/
192-
@POST
193-
public Response postNoBody(final byte[] message,
194-
final @Context UriInfo uriInfo, final @Context HttpHeaders headers) {
155+
156+
// Check that POST or PUT is valid and then update namespace.
157+
private Response processUpdate(NamespacesInstanceModel model, final boolean updateExisting,
158+
final UriInfo uriInfo) {
195159
if (LOG.isTraceEnabled()) {
196-
LOG.trace("POST " + uriInfo.getAbsolutePath());
160+
LOG.trace((updateExisting ? "PUT " : "POST ") + uriInfo.getAbsolutePath());
197161
}
198-
servlet.getMetrics().incrementRequests(1);
199-
try{
200-
NamespacesInstanceModel model = new NamespacesInstanceModel(namespace);
201-
return processUpdate(model, false, uriInfo);
202-
}catch(IOException ioe){
203-
servlet.getMetrics().incrementFailedPutRequests(1);
204-
throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
162+
if (model == null) {
163+
try {
164+
model = new NamespacesInstanceModel(namespace);
165+
} catch(IOException ioe) {
166+
servlet.getMetrics().incrementFailedPutRequests(1);
167+
throw new RuntimeException("Cannot retrieve info for '" + namespace + "'.");
168+
}
205169
}
206-
}
170+
servlet.getMetrics().incrementRequests(1);
207171

208-
// Check that POST or PUT is valid and then update namespace.
209-
private Response processUpdate(final NamespacesInstanceModel model, final boolean updateExisting,
210-
final UriInfo uriInfo) {
211172
if (servlet.isReadOnly()) {
212173
servlet.getMetrics().incrementFailedPutRequests(1);
213174
return Response.status(Response.Status.FORBIDDEN).type(MIMETYPE_TEXT)
@@ -265,7 +226,9 @@ private Response createOrUpdate(final NamespacesInstanceModel model, final UriIn
265226
}
266227

267228
servlet.getMetrics().incrementSucessfulPutRequests(1);
268-
return Response.created(uriInfo.getAbsolutePath()).build();
229+
230+
return updateExisting ? Response.ok(uriInfo.getAbsolutePath()).build() :
231+
Response.created(uriInfo.getAbsolutePath()).build();
269232
}
270233

271234
private boolean doesNamespaceExist(Admin admin, String namespaceName) throws IOException{

hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/model/NamespacesInstanceModel.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,5 @@ public ProtobufMessageHandler getObjectFromMessage(byte[] message) throws IOExce
166166
}
167167
return this;
168168
}
169+
169170
}

hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestNamespacesInstanceResource.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.apache.hadoop.hbase.testclassification.MediumTests;
5151
import org.apache.hadoop.hbase.testclassification.RestTests;
5252
import org.apache.hadoop.hbase.util.Bytes;
53+
import org.apache.http.Header;
5354
import org.junit.AfterClass;
5455
import org.junit.BeforeClass;
5556
import org.junit.ClassRule;
@@ -329,6 +330,12 @@ public void testNamespaceCreateAndDeleteXMLAndJSON() throws IOException, JAXBExc
329330
jsonString = jsonMapper.writeValueAsString(model2);
330331
response = client.post(namespacePath2, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString));
331332
assertEquals(201, response.getCode());
333+
//check passing null content-type with a payload returns 415
334+
Header[] nullHeaders = null;
335+
response = client.post(namespacePath1, nullHeaders, toXML(model1));
336+
assertEquals(415, response.getCode());
337+
response = client.post(namespacePath1, nullHeaders, Bytes.toBytes(jsonString));
338+
assertEquals(415, response.getCode());
332339

333340
// Check that created namespaces correctly.
334341
nd1 = findNamespace(admin, NAMESPACE1);
@@ -379,16 +386,20 @@ public void testNamespaceCreateAndDeletePBAndNoBody() throws IOException, JAXBEx
379386
model4 = testNamespacesInstanceModel.buildTestModel(NAMESPACE4, NAMESPACE4_PROPS);
380387
testNamespacesInstanceModel.checkModel(model4, NAMESPACE4, NAMESPACE4_PROPS);
381388

389+
//Defines null headers for use in tests where no body content is provided, so that we set
390+
// no content-type in the request
391+
Header[] nullHeaders = null;
392+
382393
// Test cannot PUT (alter) non-existent namespace.
383-
response = client.put(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
394+
response = client.put(namespacePath3, nullHeaders, new byte[]{});
384395
assertEquals(403, response.getCode());
385396
response = client.put(namespacePath4, Constants.MIMETYPE_PROTOBUF,
386397
model4.createProtobufOutput());
387398
assertEquals(403, response.getCode());
388399

389400
// Test cannot create tables when in read only mode.
390401
conf.set("hbase.rest.readonly", "true");
391-
response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
402+
response = client.post(namespacePath3, nullHeaders, new byte[]{});
392403
assertEquals(403, response.getCode());
393404
response = client.put(namespacePath4, Constants.MIMETYPE_PROTOBUF,
394405
model4.createProtobufOutput());
@@ -399,12 +410,16 @@ public void testNamespaceCreateAndDeletePBAndNoBody() throws IOException, JAXBEx
399410
assertNull(nd4);
400411
conf.set("hbase.rest.readonly", "false");
401412

402-
// Create namespace via no body and protobuf.
403-
response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
413+
// Create namespace with no body and binary content type.
414+
response = client.post(namespacePath3, nullHeaders, new byte[]{});
404415
assertEquals(201, response.getCode());
416+
// Create namespace with protobuf content-type.
405417
response = client.post(namespacePath4, Constants.MIMETYPE_PROTOBUF,
406418
model4.createProtobufOutput());
407419
assertEquals(201, response.getCode());
420+
//check setting unsupported content-type returns 415
421+
response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
422+
assertEquals(415, response.getCode());
408423

409424
// Check that created namespaces correctly.
410425
nd3 = findNamespace(admin, NAMESPACE3);
@@ -415,7 +430,7 @@ public void testNamespaceCreateAndDeletePBAndNoBody() throws IOException, JAXBEx
415430
checkNamespaceProperties(nd4, NAMESPACE4_PROPS);
416431

417432
// Check cannot post tables that already exist.
418-
response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
433+
response = client.post(namespacePath3, nullHeaders, new byte[]{});
419434
assertEquals(403, response.getCode());
420435
response = client.post(namespacePath4, Constants.MIMETYPE_PROTOBUF,
421436
model4.createProtobufOutput());

0 commit comments

Comments
 (0)