Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add statusCode field for CommonResponse #560

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
974cbaa
[Automated] Update the native jar versions
ayeshLK May 9, 2022
559b58a
[Automated] Update the native jar versions
ayeshLK May 9, 2022
0980882
[Automated] Update the native jar versions
ayeshLK May 9, 2022
b9d726d
Resolve merge conflicts
ayeshLK May 19, 2022
8ecd063
Merge remote-tracking branch 'upstream/main' into main
ayeshLK May 23, 2022
13c8de4
Merge remote-tracking branch 'upstream/main' into common_response_update
ayeshLK May 26, 2022
790583e
[Automated] Update the native jar versions
ayeshLK Jun 1, 2022
9d55322
Add statusCode to the CommonResponse
ayeshLK Jun 2, 2022
08f6ac4
Merge remote-tracking branch 'upstream/main' into common_response_update
ayeshLK Jun 2, 2022
5cd4828
Refactor code base
ayeshLK Jun 2, 2022
caa6c05
Migrate publisher client API to support status-code in response
ayeshLK Jun 2, 2022
e049c8f
Migrate hub client API to support statusCode in CommonResponse
ayeshLK Jun 2, 2022
9b58c91
Add status code for listener life-cycle events
ayeshLK Jun 2, 2022
4f7a0cf
Add client init error code
ayeshLK Jun 2, 2022
99bf7ec
Migrate hub API to use statusCode in CommonResponse
ayeshLK Jun 2, 2022
416d69d
Update test cases
ayeshLK Jun 2, 2022
39b3a7d
Update logic to use statusCode from API response to be used as HTTP r…
ayeshLK Jun 3, 2022
2fce131
Migrate compiler plugin test cases to support CommonResponse API change
ayeshLK Jun 3, 2022
c1984bb
Revert internal logic migration to use CommonResponse status code as …
ayeshLK Jun 3, 2022
eff9a5f
Merge remote-tracking branch 'upstream/main' into common_response_update
ayeshLK Jun 3, 2022
a82d05a
[Automated] Update the native jar versions
ayeshLK Jun 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "websubhub"
version = "1.3.0"
version = "1.3.1"
authors = ["Ballerina"]
keywords = ["websub", "hub", "publisher", "service", "listener", "client"]
repository = "https://github.com/ballerina-platform/module-ballerina-websubhub"
Expand All @@ -10,4 +10,4 @@ license = ["Apache-2.0"]
distribution = "2201.1.0"

[[platform.java11.dependency]]
path = "../native/build/libs/websubhub-native-1.3.0.jar"
path = "../native/build/libs/websubhub-native-1.3.1-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/CompilerPlugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ id = "websubhub-compiler-plugin"
class = "io.ballerina.stdlib.websubhub.WebSubHubCompilerPlugin"

[[dependency]]
path = "../compiler-plugin/build/libs/websubhub-compiler-plugin-1.3.0.jar"
path = "../compiler-plugin/build/libs/websubhub-compiler-plugin-1.3.1-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ modules = [
[[package]]
org = "ballerina"
name = "websubhub"
version = "1.3.0"
version = "1.3.1"
dependencies = [
{org = "ballerina", name = "crypto"},
{org = "ballerina", name = "http"},
Expand Down
74 changes: 60 additions & 14 deletions ballerina/commons.bal
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ const string DEREGISTER_TOPIC_ACTION = "deregister-topic";
const string CONTENT_PUBLISH_ACTION = "publish-content";
const string NOTIFY_UPDATE_ACTION = "notify-update";

const int LISTENER_INIT_ERROR = -1;
const int LISTENER_ATTACH_ERROR = -2;
const int LISTENER_START_ERROR = -3;
const int LISTENER_DETACH_ERROR = -4;
const int LISTENER_STOP_ERROR = -5;
const int CLIENT_INIT_ERROR = -10;

# Options to compress using Gzip or deflate.
#
# `AUTO`: When service behaves as a HTTP gateway inbound request/response accept-encoding option is set as the
Expand Down Expand Up @@ -104,10 +111,12 @@ final StatusPermanentRedirect STATUS_PERMANENT_REDIRECT = new;

# Record to represent the parent type for all the response records.
#
# + statusCode - HTTP status code for the response
# + mediaType - Content-Type of the request received
# + headers - Additional request headers received to be included in the request
# + body - Received request body
type CommonResponse record {|
int statusCode;
string? mediaType = ();
map<string|string[]>? headers = ();
string|byte[]|json|xml|map<string>? body = ();
Expand Down Expand Up @@ -271,46 +280,83 @@ public type Acknowledgement record {
};

# Common response, which could be used for `websubhub:TopicRegistrationSuccess`.
public final readonly & TopicRegistrationSuccess TOPIC_REGISTRATION_SUCCESS = {};
public final readonly & TopicRegistrationSuccess TOPIC_REGISTRATION_SUCCESS = {
statusCode: http:STATUS_OK
};

# Common response, which could be used for `websubhub:TopicRegistrationError`.
public final TopicRegistrationError TOPIC_REGISTRATION_ERROR = error TopicRegistrationError("Topic registration failed");
public final TopicRegistrationError TOPIC_REGISTRATION_ERROR = error TopicRegistrationError(
"Topic registration failed",
statusCode = http:STATUS_OK
);

# Common response, which could be used for `websubhub:TopicDeregistrationSuccess`.
public final readonly & TopicDeregistrationSuccess TOPIC_DEREGISTRATION_SUCCESS = {};
public final readonly & TopicDeregistrationSuccess TOPIC_DEREGISTRATION_SUCCESS = {
statusCode: http:STATUS_OK
};

# Common response, which could be used for `websubhub:TopicDeregistrationError`.
public final TopicDeregistrationError TOPIC_DEREGISTRATION_ERROR = error TopicDeregistrationError("Topic deregistration failed!");
public final TopicDeregistrationError TOPIC_DEREGISTRATION_ERROR = error TopicDeregistrationError(
"Topic deregistration failed!",
statusCode = http:STATUS_OK
);

# Common response, which could be used for `websubhub:Acknowledgement`.
public final readonly & Acknowledgement ACKNOWLEDGEMENT = {};
public final readonly & Acknowledgement ACKNOWLEDGEMENT = {
statusCode: http:STATUS_OK
};

# Common response, which could be used for `websubhub:UpdateMessageError`.
public final UpdateMessageError UPDATE_MESSAGE_ERROR = error UpdateMessageError("Error in accessing content");
public final UpdateMessageError UPDATE_MESSAGE_ERROR = error UpdateMessageError(
"Error in accessing content",
statusCode = http:STATUS_BAD_REQUEST
);

# Common response, which could be used for `websubhub:SubscriptionAccepted`.
public final readonly & SubscriptionAccepted SUBSCRIPTION_ACCEPTED = {};
public final readonly & SubscriptionAccepted SUBSCRIPTION_ACCEPTED = {
statusCode: http:STATUS_ACCEPTED
};

# Common response, which could be used for `websubhub:BadSubscriptionError`.
public final BadSubscriptionError BAD_SUBSCRIPTION_ERROR = error BadSubscriptionError("Bad subscription request");
public final BadSubscriptionError BAD_SUBSCRIPTION_ERROR = error BadSubscriptionError(
"Bad subscription request",
statusCode = http:STATUS_BAD_REQUEST
);

# Common response, which could be used for `websubhub:InternalSubscriptionError`.
public final InternalSubscriptionError INTERNAL_SUBSCRIPTION_ERROR = error InternalSubscriptionError("Internal error occurred while processing subscription request");
public final InternalSubscriptionError INTERNAL_SUBSCRIPTION_ERROR = error InternalSubscriptionError(
"Internal error occurred while processing subscription request",
statusCode = http:STATUS_INTERNAL_SERVER_ERROR
);

# Common response, which could be used for `websubhub:SubscriptionDeniedError`.
public final SubscriptionDeniedError SUBSCRIPTION_DENIED_ERROR = error SubscriptionDeniedError("Subscription denied");
public final SubscriptionDeniedError SUBSCRIPTION_DENIED_ERROR = error SubscriptionDeniedError(
"Subscription denied",
statusCode = http:STATUS_BAD_REQUEST
);

# Common response, which could be used for `websubhub:UnsubscriptionAccepted`.
public final readonly & UnsubscriptionAccepted UNSUBSCRIPTION_ACCEPTED = {};
public final readonly & UnsubscriptionAccepted UNSUBSCRIPTION_ACCEPTED = {
statusCode: http:STATUS_ACCEPTED
};

# Common response, which could be used for `websubhub:BadUnsubscriptionError`.
public final BadUnsubscriptionError BAD_UNSUBSCRIPTION_ERROR = error BadUnsubscriptionError("Bad unsubscription request");
public final BadUnsubscriptionError BAD_UNSUBSCRIPTION_ERROR = error BadUnsubscriptionError(
"Bad unsubscription request",
statusCode = http:STATUS_BAD_REQUEST
);

# Common response, which could be used for `websubhub:InternalUnsubscriptionError`.
public final InternalUnsubscriptionError INTERNAL_UNSUBSCRIPTION_ERROR = error InternalUnsubscriptionError("Internal error occurred while processing unsubscription request");
public final InternalUnsubscriptionError INTERNAL_UNSUBSCRIPTION_ERROR = error InternalUnsubscriptionError(
"Internal error occurred while processing unsubscription request",
statusCode = http:STATUS_INTERNAL_SERVER_ERROR
);

# Common response, which could be used for `websubhub:UnsubscriptionDeniedError`.
public final UnsubscriptionDeniedError UNSUBSCRIPTION_DENIED_ERROR = error UnsubscriptionDeniedError("Unsubscription denied");
public final UnsubscriptionDeniedError UNSUBSCRIPTION_DENIED_ERROR = error UnsubscriptionDeniedError(
"Unsubscription denied",
statusCode = http:STATUS_BAD_REQUEST
);

# Record to represent the client configuration for the HubClient/PublisherClient.
#
Expand Down
2 changes: 1 addition & 1 deletion ballerina/content_distribution.bal
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ isolated function retrieveRequestBody(string contentType, http:Request request)
return check request.getBinaryPayload();
}
_ => {
return error Error("Requested content type is not supported");
return error Error("Requested content type is not supported", statusCode = http:STATUS_BAD_REQUEST);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion ballerina/http_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,6 @@ isolated function handleResult(http:Caller caller, http:Response|error result) r
isolated function respondToRequest(http:Caller caller, http:Response response) returns Error? {
http:ListenerError? responseError = caller->respond(response);
if responseError is http:ListenerError {
return error Error("Error occurred while responding to the request ", responseError);
return error Error("Error occurred while responding to the request ", responseError, statusCode = http:STATUS_INTERNAL_SERVER_ERROR);
}
}
12 changes: 7 additions & 5 deletions ballerina/hub_client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public client class HubClient {
request.setPayload(payload);
error? result = request.setContentType(contentType);
if (result is error) {
return error Error("Error occurred while setting content type", result);
return error Error("Error occurred while setting content type", result, statusCode = http:STATUS_BAD_REQUEST);
}
request.setHeader(LINK, self.hubLinks);
string? secret = self.secret;
Expand All @@ -87,15 +87,15 @@ public client class HubClient {
if hash is byte[] {
request.setHeader(X_HUB_SIGNATURE, string `${SHA256_HMAC}=${hash.toBase16()}`);
} else {
return error Error("Error retrieving content signature", hash);
return error Error("Error retrieving content signature", hash, statusCode = http:STATUS_BAD_REQUEST);
}
}
http:Response|error response = self.httpClient->post("/", request);
if response is http:Response {
return processSubscriberResponse(response, self.topic);
} else {
string errorMsg = string `Content distribution failed for topic [${self.topic}]`;
return error ContentDeliveryError(errorMsg);
return error ContentDeliveryError(errorMsg, statusCode = http:STATUS_INTERNAL_SERVER_ERROR);
}
}
}
Expand Down Expand Up @@ -156,24 +156,26 @@ isolated function processSubscriberResponse(http:Response response, string topic
map<string|string[]> responseHeaders = retrieveResponseHeaders(response);
if responseContentType.trim().length() > 1 {
return {
statusCode: status,
headers: responseHeaders,
mediaType: responseContentType,
body: retrieveResponseBody(response, responseContentType)
};
} else {
return {
statusCode: status,
headers: responseHeaders
};
}
} else if status == http:STATUS_GONE {
// HTTP 410 is used to communicate that subscriber no longer need to continue the subscription
string errorMsg = string `Subscription to topic [${topic}] is terminated by the subscriber`;
return error SubscriptionDeletedError(errorMsg);
return error SubscriptionDeletedError(errorMsg, statusCode = status);
} else {
var result = response.getTextPayload();
string textPayload = result is string ? result : "";
string errorMsg = string `Error occurred distributing updated content: ${textPayload}`;
return error ContentDeliveryError(errorMsg);
return error ContentDeliveryError(errorMsg, statusCode = status);
}
}

Expand Down
12 changes: 6 additions & 6 deletions ballerina/hub_listener.bal
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class Listener {
if httpListener is http:Listener {
self.httpListener = httpListener;
} else {
return error Error("Listener initialization failed", httpListener);
return error Error("Listener initialization failed", httpListener, statusCode = LISTENER_INIT_ERROR);
}
} else {
self.httpListener = listenTo;
Expand Down Expand Up @@ -78,7 +78,7 @@ public class Listener {
}
error? result = self.httpListener.attach(<HttpService> self.httpService, name);
if (result is error) {
return error Error("Error occurred while attaching the service", result);
return error Error("Error occurred while attaching the service", result, statusCode = LISTENER_ATTACH_ERROR);
}
}

Expand Down Expand Up @@ -116,7 +116,7 @@ public class Listener {
public isolated function detach(Service s) returns Error? {
error? result = self.httpListener.detach(<HttpService> self.httpService);
if (result is error) {
return error Error("Error occurred while detaching the service", result);
return error Error("Error occurred while detaching the service", result, statusCode = LISTENER_DETACH_ERROR);
}
}

Expand All @@ -129,7 +129,7 @@ public class Listener {
public isolated function 'start() returns Error? {
error? listenerError = self.httpListener.'start();
if (listenerError is error) {
return error Error("Error occurred while starting the service", listenerError);
return error Error("Error occurred while starting the service", listenerError, statusCode = LISTENER_START_ERROR);
}
}

Expand All @@ -142,7 +142,7 @@ public class Listener {
public isolated function gracefulStop() returns Error? {
error? result = self.httpListener.gracefulStop();
if (result is error) {
return error Error("Error occurred while stopping the service", result);
return error Error("Error occurred while stopping the service", result, statusCode = LISTENER_STOP_ERROR);
}
}

Expand All @@ -155,7 +155,7 @@ public class Listener {
public isolated function immediateStop() returns Error? {
error? result = self.httpListener.immediateStop();
if (result is error) {
return error Error("Error occurred while stopping the service", result);
return error Error("Error occurred while stopping the service", result, statusCode = LISTENER_STOP_ERROR);
}
}
}
Expand Down
36 changes: 24 additions & 12 deletions ballerina/publisher_client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ public client class PublisherClient {
if registrationResponse is http:Response {
TopicRegistrationSuccess|error clientResponse = handleResponse(registrationResponse, topic, REGISTER_TOPIC_ACTION);
if clientResponse is error {
return error TopicRegistrationError(clientResponse.message(), clientResponse);
return error TopicRegistrationError(clientResponse.message(), clientResponse,
statusCode = registrationResponse.statusCode);
} else {
return clientResponse;
}
} else {
return error TopicRegistrationError(string `"Error sending topic registration request for topic [${topic}]`, registrationResponse);
return error TopicRegistrationError(
string `Error sending topic registration request for topic [${topic}]`, registrationResponse,
statusCode = http:STATUS_INTERNAL_SERVER_ERROR);
}
}

Expand All @@ -71,12 +74,15 @@ public client class PublisherClient {
if deregistrationResponse is http:Response {
TopicDeregistrationSuccess|error clientResponse = handleResponse(deregistrationResponse, topic, DEREGISTER_TOPIC_ACTION);
if clientResponse is error {
return error TopicDeregistrationError(clientResponse.message(), clientResponse);
return error TopicDeregistrationError(clientResponse.message(), clientResponse,
statusCode = deregistrationResponse.statusCode);
} else {
return clientResponse;
}
} else {
return error TopicDeregistrationError(string `Error sending topic deregistration request for topic [${topic}]`, deregistrationResponse);
return error TopicDeregistrationError(
string `Error sending topic deregistration request for topic [${topic}]`, deregistrationResponse,
statusCode = http:STATUS_INTERNAL_SERVER_ERROR);
}
}

Expand Down Expand Up @@ -104,20 +110,23 @@ public client class PublisherClient {
error? setContent = contentUpdateRequest.setContentType(contentType);
if setContent is error {
string errorMsg = string `Invalid content type is set, found ${contentType}`;
return error UpdateMessageError(errorMsg, setContent);
return error UpdateMessageError(errorMsg, setContent, statusCode = http:STATUS_BAD_REQUEST);
}
}
string queryParams = string `${HUB_MODE}=${MODE_PUBLISH}&${HUB_TOPIC}=${topic}`;
http:Response|error contentPublishResponse = self.httpClient->post(string `?${queryParams}`, contentUpdateRequest);
if contentPublishResponse is http:Response {
Acknowledgement|error clientResponse = handleResponse(contentPublishResponse, topic, CONTENT_PUBLISH_ACTION);
if clientResponse is error {
return error UpdateMessageError(clientResponse.message(), clientResponse);
return error UpdateMessageError(clientResponse.message(), clientResponse,
statusCode = contentPublishResponse.statusCode);
} else {
return clientResponse;
}
} else {
return error UpdateMessageError(string `Publish failed for topic [${topic}]`, contentPublishResponse);
return error UpdateMessageError(
string `Publish failed for topic [${topic}]`, contentPublishResponse,
statusCode = http:STATUS_INTERNAL_SERVER_ERROR);
}
}

Expand All @@ -137,12 +146,14 @@ public client class PublisherClient {
if notifyResponse is http:Response {
Acknowledgement|error clientResponse = handleResponse(notifyResponse, topic, NOTIFY_UPDATE_ACTION);
if clientResponse is error {
return error UpdateMessageError(clientResponse.message(), clientResponse);
return error UpdateMessageError(clientResponse.message(), clientResponse, statusCode = notifyResponse.statusCode);
} else {
return clientResponse;
}
} else {
return error UpdateMessageError(string `Update availability notification failed for topic [${topic}]`, notifyResponse);
return error UpdateMessageError(
string `Update availability notification failed for topic [${topic}]`, notifyResponse,
statusCode = http:STATUS_INTERNAL_SERVER_ERROR);
}
}
}
Expand All @@ -154,17 +165,18 @@ isolated function handleResponse(http:Response response, string topic, string ac
string errorMsg = string `Error occurred while executing ${action} action for topic [${topic}], Status code : ${response.statusCode}, payload : ${responsePayload}`;
return error(errorMsg);
} else {
map<string>? params = getFormData(responsePayload);
map<string> params = getFormData(responsePayload);
if params[HUB_MODE] == MODE_ACCEPTED {
CommonResponse successResult = {
statusCode: response.statusCode,
headers: getHeaders(response),
body: params
};
return successResult;
} else {
string? failureReason = params[HUB_REASON];
string nmm = string `Unknown error occurred while executing ${action} action for topic [${topic}]`;
string errorMsg = failureReason is string ? failureReason : nmm;
string constructedErrorMsg = string `Unknown error occurred while executing ${action} action for topic [${topic}]`;
string errorMsg = failureReason is string ? failureReason : constructedErrorMsg;
return error(errorMsg);
}
}
Expand Down
Loading