Skip to content

Commit 9981635

Browse files
authored
fix: disallow empty 'subject' context attribute (#679)
Specification clearly states that 'subject' is optional but if present, MUST be non-empty (spec at https://github.com/cloudevents/spec/blob/v1.0/spec.md#subject) Signed-off-by: Kristiyan Marinov <[email protected]>
1 parent b54df5c commit 9981635

File tree

6 files changed

+57
-3
lines changed

6 files changed

+57
-3
lines changed

core/src/main/java/io/cloudevents/core/impl/BaseCloudEventBuilder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ protected static IllegalStateException createMissingAttributeException(String at
219219
return new IllegalStateException("Attribute '" + attributeName + "' cannot be null");
220220
}
221221

222+
protected static IllegalStateException createEmptyAttributeException(String attributeName) {
223+
return new IllegalStateException("Attribute '" + attributeName + "' cannot be empty");
224+
}
225+
222226
/**
223227
* Validates the extension name as defined in CloudEvents spec.
224228
*

core/src/main/java/io/cloudevents/core/v03/CloudEventBuilder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ public CloudEventV03 build() {
124124
if (type == null) {
125125
throw createMissingAttributeException("type");
126126
}
127+
if (subject != null && subject.isEmpty()) {
128+
throw createEmptyAttributeException(("subject"));
129+
}
127130

128131
CloudEventV03 cloudEvent = new CloudEventV03(id, source, type, time, schemaurl, datacontenttype, subject, this.data, this.extensions);
129132
final CloudEventValidatorProvider validator = CloudEventValidatorProvider.getInstance();

core/src/main/java/io/cloudevents/core/v1/CloudEventBuilder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ public CloudEvent build() {
120120
if (type == null) {
121121
throw createMissingAttributeException(TYPE);
122122
}
123+
if (subject != null && subject.isEmpty()) {
124+
throw createEmptyAttributeException(("subject"));
125+
}
123126

124127
CloudEvent cloudEvent = new CloudEventV1(id, source, type, datacontenttype, dataschema, subject, time, this.data, this.extensions);
125128

core/src/test/java/io/cloudevents/core/v03/CloudEventBuilderTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,4 +158,27 @@ void testMissingType() {
158158
).hasMessageContaining("Attribute 'type' cannot be null");
159159
}
160160

161+
@Test
162+
void testMissingSubject() {
163+
CloudEvent actual = CloudEventBuilder
164+
.v03()
165+
.withId("000")
166+
.withSource(URI.create("http://localhost"))
167+
.withType(TYPE)
168+
.build();
169+
170+
assertThat(actual).isNotNull();
171+
}
172+
173+
@Test
174+
void testEmptySubject() {
175+
assertThatCode(() -> CloudEventBuilder
176+
.v03()
177+
.withId("000")
178+
.withSource(URI.create("http://localhost"))
179+
.withType(TYPE)
180+
.withSubject("")
181+
.build()
182+
).hasMessageContaining("Attribute 'subject' cannot be empty");
183+
}
161184
}

core/src/test/java/io/cloudevents/core/v1/CloudEventBuilderTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,27 @@ void testValidatorProvider(){
154154
).hasMessageContaining("Expecting sales in namespace extension");
155155
}
156156

157+
@Test
158+
void testMissingSubject() {
159+
CloudEvent actual = CloudEventBuilder
160+
.v1()
161+
.withId("000")
162+
.withSource(URI.create("http://localhost"))
163+
.withType(TYPE)
164+
.build();
165+
166+
assertThat(actual).isNotNull();
167+
}
168+
169+
@Test
170+
void testEmptySubject() {
171+
assertThatCode(() -> CloudEventBuilder
172+
.v1()
173+
.withId("000")
174+
.withSource(URI.create("http://localhost"))
175+
.withType(TYPE)
176+
.withSubject("")
177+
.build()
178+
).hasMessageContaining("Attribute 'subject' cannot be empty");
179+
}
157180
}

formats/avro-compact/src/test/java/io/cloudevents/avro/compact/AvroCompactFormatTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void format() {
4848
.withType("")
4949
// optional
5050
.withTime(Instant.EPOCH.atOffset(ZoneOffset.UTC))
51-
.withSubject("")
51+
.withSubject("subject")
5252
.withDataSchema(URI.create(""))
5353
// extension
5454
// support boolean, int, long, string, bytes
@@ -71,7 +71,5 @@ void format() {
7171
byte[] reserialized = format.serialize(deserialized);
7272

7373
assertArrayEquals(serialized, reserialized);
74-
75-
7674
}
7775
}

0 commit comments

Comments
 (0)